github.com/infraboard/keyauth@v0.8.1/cmd/start.go (about) 1 package cmd 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "os" 8 "os/signal" 9 "strings" 10 "syscall" 11 12 "github.com/infraboard/mcube/app" 13 "github.com/infraboard/mcube/cache" 14 "github.com/infraboard/mcube/cache/memory" 15 "github.com/infraboard/mcube/cache/redis" 16 "github.com/infraboard/mcube/logger" 17 "github.com/infraboard/mcube/logger/zap" 18 "github.com/spf13/cobra" 19 20 "github.com/infraboard/keyauth/conf" 21 "github.com/infraboard/keyauth/protocol" 22 23 // 加载所有服务 24 _ "github.com/infraboard/keyauth/apps/all" 25 ) 26 27 var ( 28 // pusher service config option 29 confType string 30 confFile string 31 ) 32 33 // startCmd represents the start command 34 var serviceCmd = &cobra.Command{ 35 Use: "start", 36 Short: "启动权限中心服务", 37 Long: `启动权限中心服务`, 38 RunE: func(cmd *cobra.Command, args []string) error { 39 // 初始化全局变量 40 if err := loadGlobalConfig(confType); err != nil { 41 return err 42 } 43 44 // 初始化全局组件 45 if err := loadGlobalComponent(); err != nil { 46 return err 47 } 48 49 // 初始化所有服务 50 if err := app.InitAllApp(); err != nil { 51 return err 52 } 53 54 conf := conf.C() 55 // 启动服务 56 ch := make(chan os.Signal, 1) 57 signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP, syscall.SIGQUIT) 58 59 // 初始化服务 60 svr, err := newService(conf) 61 if err != nil { 62 return err 63 } 64 65 // 等待信号处理 66 go svr.waitSign(ch) 67 68 // 启动服务 69 if err := svr.start(); err != nil { 70 if !strings.Contains(err.Error(), "http: Server closed") { 71 return err 72 } 73 } 74 75 return nil 76 }, 77 } 78 79 func newService(cnf *conf.Config) (*service, error) { 80 log := zap.L().Named("CLI") 81 http := protocol.NewHTTPService() 82 grpc := protocol.NewGRPCService() 83 84 // 初始化总线 85 // bm, err := newBus() 86 // if err != nil { 87 // log.Errorf("new bus error, %s", err) 88 // } 89 90 svr := &service{ 91 http: http, 92 grpc: grpc, 93 // bm: bm, 94 log: log, 95 } 96 97 return svr, nil 98 } 99 100 type service struct { 101 http *protocol.HTTPService 102 grpc *protocol.GRPCService 103 // bm bus.Manager 104 105 log logger.Logger 106 stop context.CancelFunc 107 } 108 109 func (s *service) start() error { 110 // if s.bm != nil { 111 // if err := s.bm.Connect(); err != nil { 112 // s.log.Errorf("connect bus error, %s", err) 113 // } 114 // } 115 116 s.log.Infof("loaded grpc app: %s", app.LoadedGrpcApp()) 117 s.log.Infof("loaded http app: %s", app.LoadedHttpApp()) 118 s.log.Infof("loaded internal app: %s", app.LoadedInternalApp()) 119 120 go s.grpc.Start() 121 return s.http.Start() 122 } 123 124 // config 为全局变量, 只需要load 即可全局可用户 125 func loadGlobalConfig(configType string) error { 126 // 配置加载 127 switch configType { 128 case "file": 129 err := conf.LoadConfigFromToml(confFile) 130 if err != nil { 131 return err 132 } 133 case "env": 134 err := conf.LoadConfigFromEnv() 135 if err != nil { 136 return err 137 } 138 return nil 139 default: 140 return errors.New("unknown config type") 141 } 142 143 return nil 144 } 145 146 func loadGlobalComponent() error { 147 // 初始化全局日志配置 148 if err := loadGlobalLogger(); err != nil { 149 return err 150 } 151 152 // 加载缓存 153 if err := loadCache(); err != nil { 154 return err 155 } 156 return nil 157 } 158 159 // log 为全局变量, 只需要load 即可全局可用户, 依赖全局配置先初始化 160 func loadGlobalLogger() error { 161 var ( 162 logInitMsg string 163 level zap.Level 164 ) 165 166 lc := conf.C().Log 167 lv, err := zap.NewLevel(lc.Level) 168 if err != nil { 169 logInitMsg = fmt.Sprintf("%s, use default level INFO", err) 170 level = zap.InfoLevel 171 } else { 172 level = lv 173 logInitMsg = fmt.Sprintf("log level: %s", lv) 174 } 175 176 zapConfig := zap.DefaultConfig() 177 zapConfig.Level = level 178 179 switch lc.To { 180 case conf.ToStdout: 181 zapConfig.ToStderr = true 182 zapConfig.ToFiles = false 183 case conf.ToFile: 184 zapConfig.Files.Name = "api.log" 185 zapConfig.Files.Path = lc.PathDir 186 } 187 188 switch lc.Format { 189 case conf.JSONFormat: 190 zapConfig.JSON = true 191 } 192 193 if err := zap.Configure(zapConfig); err != nil { 194 return err 195 } 196 197 zap.L().Named("INIT").Info(logInitMsg) 198 return nil 199 } 200 201 func loadCache() error { 202 l := zap.L().Named("INIT") 203 c := conf.C() 204 // 设置全局缓存 205 switch c.Cache.Type { 206 case "memory", "": 207 ins := memory.NewCache(c.Cache.Memory) 208 cache.SetGlobal(ins) 209 l.Info("use cache in local memory") 210 case "redis": 211 ins := redis.NewCache(c.Cache.Redis) 212 cache.SetGlobal(ins) 213 l.Info("use redis to cache") 214 default: 215 return fmt.Errorf("unknown cache type: %s", c.Cache.Type) 216 } 217 218 return nil 219 } 220 221 // func newBus() (bus.Manager, error) { 222 // c := conf.C() 223 // if c.Nats != nil { 224 // ns, err := nats.NewBroker(c.Nats) 225 // if err != nil { 226 // return nil, err 227 // } 228 // bus.SetPublisher(ns) 229 // return ns, nil 230 // } 231 232 // if c.Kafka != nil { 233 // ks, err := kafka.NewPublisher(c.Kafka) 234 // if err != nil { 235 // return nil, err 236 // } 237 // bus.SetPublisher(ks) 238 // return ks, nil 239 // } 240 241 // return nil, fmt.Errorf("bus not config, nats or kafka required") 242 // } 243 244 func (s *service) waitSign(sign chan os.Signal) { 245 for { 246 select { 247 case sg := <-sign: 248 switch v := sg.(type) { 249 default: 250 s.log.Infof("receive signal '%v', start graceful shutdown", v.String()) 251 if err := s.grpc.Stop(); err != nil { 252 s.log.Errorf("grpc graceful shutdown err: %s, force exit", err) 253 } 254 s.log.Info("grpc service stop complete") 255 if err := s.http.Stop(); err != nil { 256 s.log.Errorf("http graceful shutdown err: %s, force exit", err) 257 } 258 s.log.Infof("http service stop complete") 259 return 260 } 261 } 262 } 263 } 264 265 func init() { 266 serviceCmd.Flags().StringVarP(&confType, "config-type", "t", "file", "the service config type [file/env/etcd]") 267 serviceCmd.Flags().StringVarP(&confFile, "config-file", "f", "etc/keyauth.toml", "the service config from file") 268 RootCmd.AddCommand(serviceCmd) 269 }