func (this *Gateway) InstanceInfo() []byte { ip, err := ctx.LocalIP() if err != nil { panic(err) } info := gzk.KatewayMeta{ Id: this.id, Zone: Options.Zone, Ver: gafka.Version, Build: gafka.BuildId, BuiltAt: gafka.BuiltAt, Host: ctx.Hostname(), Ip: ip.String(), Cpu: ctx.NumCPUStr(), Arch: fmt.Sprintf("%s:%s-%s/%s", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH), PubAddr: Options.PubHttpAddr, SPubAddr: Options.PubHttpsAddr, SubAddr: Options.SubHttpAddr, SSubAddr: Options.SubHttpsAddr, ManAddr: Options.ManHttpAddr, SManAddr: Options.ManHttpsAddr, DebugAddr: Options.DebugHttpAddr, } d, _ := json.Marshal(info) return d }
func NewSubStore(closedConnCh <-chan string, debug bool) *subStore { if debug { sarama.Logger = l.New(os.Stdout, color.Blue("[Sarama]"), l.LstdFlags|l.Lshortfile) } return &subStore{ hostname: ctx.Hostname(), shutdownCh: make(chan struct{}), closedConnCh: closedConnCh, } }
func NewPubStore(poolCapcity int, idleTimeout time.Duration, compress bool, debug bool, dryRun bool) *pubStore { if debug { sarama.Logger = l.New(os.Stdout, color.Green("[Sarama]"), l.LstdFlags|l.Lshortfile) } return &pubStore{ hostname: ctx.Hostname(), compress: compress, idleTimeout: idleTimeout, pubPoolsCapcity: poolCapcity, pubPools: make(map[string]*pubPool), dryRun: dryRun, shutdownCh: make(chan struct{}), } }
func (this *Gateway) Start() (err error) { log.Info("starting gateway[%s@%s]...", gafka.BuildId, gafka.BuiltAt) signal.RegisterHandler(func(sig os.Signal) { this.shutdownOnce.Do(func() { log.Info("gateway[%s@%s] received signal: %s", gafka.BuildId, gafka.BuiltAt, strings.ToUpper(sig.String())) close(this.quiting) }) }, syscall.SIGINT, syscall.SIGTERM) // yes we ignore HUP // keep watch on zk connection jitter go this.healthCheck() meta.Default.Start() log.Trace("meta store[%s] started", meta.Default.Name()) if err = manager.Default.Start(); err != nil { return } log.Trace("manager store[%s] started", manager.Default.Name()) if telemetry.Default != nil { go func() { log.Trace("telemetry[%s] started", telemetry.Default.Name()) if err = telemetry.Default.Start(); err != nil { log.Error("telemetry[%s]: %v", telemetry.Default.Name(), err) } }() } if Options.EnableAccessLog { if err = this.accessLogger.Start(); err != nil { log.Error("access logger: %s", err) } } this.buildRouting() this.svrMetrics.Load() go startRuntimeMetrics(Options.ReporterInterval) // start up the servers this.manServer.Start() // man server is always present if this.pubServer != nil { if err = store.DefaultPubStore.Start(); err != nil { panic(err) } log.Trace("pub store[%s] started", store.DefaultPubStore.Name()) if err = hh.Default.Start(); err != nil { return } log.Trace("hh[%s] started", hh.Default.Name()) if err = job.Default.Start(); err != nil { panic(err) } log.Trace("job store[%s] started", job.Default.Name()) this.pubServer.Start() } if this.subServer != nil { if err = store.DefaultSubStore.Start(); err != nil { panic(err) } log.Trace("sub store[%s] started", store.DefaultSubStore.Name()) this.subServer.Start() } // the last thing is to register: notify others: come on baby! if registry.Default != nil { registry.Default.Register(this.id, this.InstanceInfo()) log.Info("gateway[%s:%s] ready, registered in %s :-)", ctx.Hostname(), this.id, registry.Default.Name()) } else { log.Info("gateway[%s:%s] ready, unregistered", ctx.Hostname(), this.id) } return nil }
func (this *Kateway) Run(args []string) (exitCode int) { cmdFlags := flag.NewFlagSet("kateway", flag.ContinueOnError) cmdFlags.Usage = func() { this.Ui.Output(this.Help()) } cmdFlags.StringVar(&this.zone, "z", "", "") cmdFlags.BoolVar(&this.configMode, "cf", false, "") cmdFlags.StringVar(&this.id, "id", "", "") cmdFlags.BoolVar(&this.install, "i", false, "") cmdFlags.BoolVar(&this.longFmt, "l", false, "") cmdFlags.StringVar(&this.configOption, "option", "", "") cmdFlags.BoolVar(&this.versionOnly, "ver", false, "") cmdFlags.BoolVar(&this.flameGraph, "flame", false, "") cmdFlags.StringVar(&this.logLevel, "loglevel", "", "") cmdFlags.StringVar(&this.visualLog, "visualog", "", "") cmdFlags.BoolVar(&this.showZkNodes, "zk", false, "") cmdFlags.BoolVar(&this.checkup, "checkup", false, "") cmdFlags.BoolVar(&this.benchmark, "bench", false, "") cmdFlags.StringVar(&this.benchmarkMaster, "master", "", "") cmdFlags.BoolVar(&this.pub, "pub", false, "") cmdFlags.BoolVar(&this.sub, "sub", false, "") cmdFlags.BoolVar(&this.benchmarkAsync, "async", false, "") cmdFlags.BoolVar(&this.curl, "curl", false, "") if err := cmdFlags.Parse(args); err != nil { return 2 } if this.benchmark { if validateArgs(this, this.Ui). require("-z"). requireAdminRights("-z"). invalid(args) { return 2 } zkzone := zk.NewZkZone(zk.DefaultConfig(this.zone, ctx.ZoneZkAddrs(this.zone))) zone := ctx.Zone(zkzone.Name()) this.benchApp = zone.SmokeApp this.benchSecret = zone.SmokeSecret this.benchTopic = zone.SmokeTopic this.benchVer = zone.SmokeTopicVersion this.benchPubEndpoint = zone.PubEndpoint if this.id != "" { kws, err := zkzone.KatewayInfos() swallow(err) for _, kw := range kws { if kw.Id == this.id { this.benchPubEndpoint = kw.PubAddr break } } } this.benchId = fmt.Sprintf("%s-%s", ctx.Hostname(), strings.Replace(uuid.New(), "-", "", -1)) this.runBenchmark(zkzone) return } if this.flameGraph { if validateArgs(this, this.Ui). require("-z", "-id"). requireAdminRights("-z"). invalid(args) { return 2 } zkzone := zk.NewZkZone(zk.DefaultConfig(this.zone, ctx.ZoneZkAddrs(this.zone))) this.generateFlameGraph(zkzone) return } if this.visualLog != "" { this.doVisualize() return } if this.pub { zkzone := zk.NewZkZone(zk.DefaultConfig(this.zone, ctx.ZoneZkAddrs(this.zone))) this.runPub(zkzone) return } if this.sub { zkzone := zk.NewZkZone(zk.DefaultConfig(this.zone, ctx.ZoneZkAddrs(this.zone))) this.runSub(zkzone) return } if this.install { if validateArgs(this, this.Ui). require("-z"). invalid(args) { return 2 } zkzone := zk.NewZkZone(zk.DefaultConfig(this.zone, ctx.ZoneZkAddrs(this.zone))) this.installGuide(zkzone) return } if this.configOption != "" { this.configMode = true } if this.configMode { if validateArgs(this, this.Ui). require("-z"). requireAdminRights("-z"). invalid(args) { return 2 } zkzone := zk.NewZkZone(zk.DefaultConfig(this.zone, ctx.ZoneZkAddrs(this.zone))) if this.logLevel != "" { if this.id != "" { kw := zkzone.KatewayInfoById(this.id) if kw == nil { panic(fmt.Sprintf("kateway %s invalid entry found in zk", this.id)) } this.callKateway(kw, "PUT", fmt.Sprintf("v1/log/%s", this.logLevel)) } else { // apply on all kateways kws, _ := zkzone.KatewayInfos() for _, kw := range kws { this.callKateway(kw, "PUT", fmt.Sprintf("v1/log/%s", this.logLevel)) } } } if this.configOption != "" { parts := strings.SplitN(this.configOption, "=", 2) if len(parts) != 2 { this.Ui.Error("usage: key=value") return } k, v := parts[0], parts[1] if this.id != "" { kw := zkzone.KatewayInfoById(this.id) if kw == nil { panic(fmt.Sprintf("kateway %s invalid entry found in zk", this.id)) } this.callKateway(kw, "PUT", fmt.Sprintf("v1/options/%s/%s", k, v)) } else { // apply on all kateways kws, _ := zkzone.KatewayInfos() for _, kw := range kws { this.callKateway(kw, "PUT", fmt.Sprintf("v1/options/%s/%s", k, v)) } } } return } if this.checkup { if this.zone == "" { forAllSortedZones(func(zkzone *zk.ZkZone) { this.runCheckup(zkzone) }) return } zkzone := zk.NewZkZone(zk.DefaultConfig(this.zone, ctx.ZoneZkAddrs(this.zone))) this.runCheckup(zkzone) return } if this.showZkNodes { this.Ui.Output(fmt.Sprintf(`%s pubsub manager db dsn %s job db cluster config %s turn off webhook dir`, color.Green("%-50s", zk.KatewayMysqlPath), color.Green("%-50s", zk.PubsubJobConfig), color.Green("%-50s", zk.PubsubWebhooksOff))) return } // display mode lines := make([]string, 0) header := "Zone|Id|Ip|Pprof|Build|Cpu|Heap|Obj|Go|P/S|hhIn/hhOut|Uptime" lines = append(lines, header) forSortedZones(func(zkzone *zk.ZkZone) { if this.zone != "" && zkzone.Name() != this.zone { return } if !this.versionOnly { mysqlDsn, err := zkzone.KatewayMysqlDsn() if err != nil { this.Ui.Warn(fmt.Sprintf("kateway[%s] mysql DSN not set on zk yet", zkzone.Name())) this.Ui.Output(fmt.Sprintf("e,g. %s -> pubsub:pubsub@tcp(10.77.135.217:10010)/pubsub?charset=utf8&timeout=10s", zk.KatewayMysqlPath)) } else { this.Ui.Output(fmt.Sprintf("zone[%s] manager db: %s", color.Cyan(zkzone.Name()), mysqlDsn)) } } kateways, err := zkzone.KatewayInfos() if err != nil { if err == zklib.ErrNoNode { this.Ui.Output("no kateway running") return } else { swallow(err) } } for _, kw := range kateways { if this.id != "" && this.id != kw.Id { continue } statusMap, _ := this.getKatewayStatusMap(kw.ManAddr) logLevel, _ := statusMap["loglevel"].(string) heapSize, _ := statusMap["heap"].(string) heapObjs, _ := statusMap["objects"].(string) pubConn, _ := statusMap["pubconn"].(string) hhAppendN, _ := statusMap["hh_appends"].(string) hhDeliverN, _ := statusMap["hh_delivers"].(string) subConn, _ := statusMap["subconn"].(string) goN, _ := statusMap["goroutines"].(string) if this.versionOnly { pprofAddr := kw.DebugAddr if len(pprofAddr) > 0 && pprofAddr[0] == ':' { pprofAddr = kw.Ip + pprofAddr } pprofAddr = fmt.Sprintf("%s/debug/pprof/", pprofAddr) lines = append(lines, fmt.Sprintf("%s|%s|%s|%s|%s/%s|%s|%s|%s|%s|%s/%s|%s/%s|%s", zkzone.Name(), kw.Id, kw.Ip, pprofAddr, kw.Build, kw.BuiltAt, kw.Cpu, heapSize, heapObjs, goN, pubConn, subConn, hhAppendN, hhDeliverN, gofmt.PrettySince(kw.Ctime))) continue } this.Ui.Info(fmt.Sprintf("id:%-2s host:%s cpu:%-2s up:%s", kw.Id, kw.Host, kw.Cpu, gofmt.PrettySince(kw.Ctime))) this.Ui.Output(fmt.Sprintf(" ver: %s\n arch: %s\n build: %s\n built: %s\n log: %s\n pub: %s\n sub: %s\n man: %s\n dbg: %s", kw.Ver, kw.Arch, color.Red(kw.Build), kw.BuiltAt, logLevel, kw.PubAddr, kw.SubAddr, kw.ManAddr, kw.DebugAddr, )) if this.longFmt { this.Ui.Output(" full status:") this.Ui.Output(this.getKatewayStatus(kw.ManAddr)) } } }) if this.versionOnly && len(lines) > 1 { fmt.Println(columnize.SimpleFormat(lines)) } return }
func (this *Gateway) Start() (err error) { log.Trace("starting gateway...") signal.RegisterSignalsHandler(func(sig os.Signal) { log.Info("received signal: %s", strings.ToUpper(sig.String())) this.stop() }, syscall.SIGINT, syscall.SIGTERM) // yes we ignore HUP meta.Default.Start() log.Trace("meta store[%s] started", meta.Default.Name()) if err = manager.Default.Start(); err != nil { return } log.Trace("manager store[%s] started", manager.Default.Name()) go this.watchDeadPartitions() go this.guard.Start() log.Trace("guard started") if Options.EnableAccessLog { if err = this.accessLogger.Start(); err != nil { log.Error("access logger: %s", err) } } this.buildRouting() if Options.DebugHttpAddr != "" { log.Info("debug http server ready on %s", Options.DebugHttpAddr) go http.ListenAndServe(Options.DebugHttpAddr, nil) } this.svrMetrics.Load() go startRuntimeMetrics(Options.ReporterInterval) // start up the servers if this.manServer != nil { this.manServer.Start() } if this.pubServer != nil { if err := store.DefaultPubStore.Start(); err != nil { panic(err) } log.Trace("pub store[%s] started", store.DefaultPubStore.Name()) this.pubServer.Start() } if this.subServer != nil { if err := store.DefaultSubStore.Start(); err != nil { panic(err) } log.Trace("sub store[%s] started", store.DefaultSubStore.Name()) this.subServer.Start() } // the last thing is to register: notify others: come on baby! if registry.Default != nil { if err := registry.Default.Register(); err != nil { panic(err) } log.Info("gateway[%s:%s] ready, registered in %s", ctx.Hostname(), this.id, registry.Default.Name()) } else { log.Info("gateway[%s:%s] ready, unregistered", ctx.Hostname(), this.id) } return nil }