func (h *HttpServer) httpListen(mux *http.ServeMux, network, addr string) { httpServer := &http.Server{Handler: mux} httpServer.SetKeepAlivesEnabled(true) l, err := net.Listen(network, addr) if err != nil { log.Fatalf("HttpServer listen (%s@%s) failed : %v", network, addr, err) panic(err) } if err := httpServer.Serve(l); err != nil { log.Fatalf("HttpServer.Serve() failed : %v", err) panic(err) } }
func main() { flag.Parse() // init config if err := InitConfig(); err != nil { log.Fatalf("InitConfig failed : %v", err) panic(err) } fmt.Println("init configure successful") isDebug = Conf.Common.Debug runtime.GOMAXPROCS(Conf.Common.MaxProc) // set log if err := InitLog(Conf.Log); err != nil { log.Fatalf("init log failed : %v", err) fmt.Printf("init log failed : %v", err) panic(err) } defer log.Close() log.Infof("init log successful") // init pprof perf.Init(Conf.Common.PprofBind) // server CometServer = NewServer() if err := CometServer.Init(); err != nil { log.Fatalf("CometServer.Init failed : %v", err) panic(err) } log.Infof("init comet server successful") // rpc server if err := InitRPC(); err != nil { log.Fatalf("InitRpcServer failed : %v", err) panic(err) } log.Infof("init rpc server successful") Conf.RegisterUpdateNotify(CometServer.UpdateConfig) Conf.RegisterUpdateNotify(UpdateRpcConfig) // wait signal signal.RegisterExit(CometServer.UnInit) signal.RegisterExit(UnInitRPC) signal.RegisterReload(reload) signal.WaitSignal() }
// @TODO only update AdminRpc which need to update func (r *AdminRpcs) UpdateConfig() { var err error config := Conf.Server.RpcAdmin rpcs := make(map[string]*AdminRpc, 0) // init admin rpc for _, node := range config { adminRpc := NewAdminRpc() if err = adminRpc.Init(node); err != nil { break } else { rpcs[node.Name] = adminRpc } } if err == nil && len(rpcs) != 0 { r.UnInit() r.Config = config r.adminRpc = rpcs for k, _ := range r.adminRpc { r.CHash.Add(k) } } else { log.Fatalf("admin rpc update config failed") } }
// update configuration. // @TODO failback, if init failed, keep original cometRpc available func (c *CometRpc) UpdateConfig() { c.UnInit() err := c.Init() if err != nil { log.Fatalf("CometRpc.UpdateConfig failed : %v", err) } }
// if comet crash : call http://admin/server?id=xx as DELETE method, and restart comet // keep rpc available func (r *AdminRpc) Keepalive(quit chan struct{}, network, address string) { if r.Client == nil { log.Fatalf("keepalive rpc with admin : rpc.Client is nil") panic(ErrAdminRpc) } var ( err error call *rpc.Call done = make(chan *rpc.Call, 1) args = proto.NoREQ{} reply = proto.PingRES{} firstPingTime int64 ) for { select { case <-quit: return default: if r.Client != nil { call = <-r.Client.Go(adminRpcPing, &args, &reply, done).Done if call.Error != nil { log.Errorf("adminRpc ping %s failed : %v", address, call.Error) } else { if firstPingTime == 0 { firstPingTime = reply.TimeUnix } // if firstPingTime difference : admin is crash. lost all user infomation if firstPingTime != reply.TimeUnix { // @TODO client maybe disconnect while doing ReSubAll, // so, comet need to send all online users to admin later? err := CometServer.ReSubAll() if err == nil { firstPingTime = reply.TimeUnix } } } } if r.Client == nil || (call != nil && call.Error == rpc.ErrShutdown) { //if isDebug { // log.Debugf("rpc.Dial (%s@%s) failed : %v", network, address, err) //} if r.Client, err = rpc.Dial(network, address); err == nil { } else { log.Errorf("adminRpc dial error : %v", err) } } } // @TODO : configuration heartbeat between comet and admin time.Sleep(5 * time.Second) } }
// init Rpc client func (r *AdminRpc) Init(conf ConfigRpcAdmin) (err error) { network := conf.Network addr := conf.Addr r.Client, err = rpc.Dial(network, addr) if err != nil || r.Client == nil { log.Fatalf("adminRpc.Dial(%s@%s) failed : %s", network, addr, err) panic(err) } r.adminRpcQuit = make(chan struct{}, 1) go r.Keepalive(r.adminRpcQuit, network, addr) log.Infof("Init admin Rpc (%s@%s) sub successfuls", network, addr) return }
func rpcListen(network, addr string) { l, err := net.Listen(network, addr) if err != nil { log.Fatalf("Rpc listen(%s, %s) failed(%v)", network, addr, err) panic(err) } log.Infof("Rpc listen(%s@%s) successful", network, addr) defer func() { log.Infof("net.Listen(%s, %s) closed", network, addr) if err := l.Close(); err != nil { log.Errorf("Rpc Close() failed(%v)", err) } }() rpc.Accept(l) }
// StartPprof start http pprof. func Init(pprofBind []string) { // pprofServeMux := http.NewServeMux() // pprofServeMux.HandleFunc("/debug/pprof/", pprof.Index) // pprofServeMux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) // pprofServeMux.HandleFunc("/debug/pprof/profile", pprof.Profile) // pprofServeMux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) // pprofServeMux.HandleFunc("/debug/pprof/trace", pprof.Trace) for _, addr := range pprofBind { go func() { if err := http.ListenAndServe(addr, nil); err != nil { log.Fatalf("perf.Init failed : %v", err) panic(err) } else { log.Infof("perf listen addr : %v", addr) } }() } }
func (r *PushRpcs) UpdateConfig() { var err error config := Conf.Server.RpcPush pushrpc := make([]*PushRpc, 0) for _, node := range config { rpc := NewPushRpc() if err = rpc.Init(node); err != nil { continue } else { pushrpc = append(pushrpc, rpc) } } if err == nil && len(pushrpc) != 0 { for _, rpc := range r.pushRpc { rpc.Close() } r.Config = config r.pushRpc = pushrpc } else { log.Fatalf("push rpc update config failed") } }