// handle unix signals func sig_handler() { defer utils.PrintPanicStack() ch := make(chan os.Signal, 1) signal.Notify(ch, syscall.SIGTERM) for { msg := <-ch //当接收到关闭信号时,要等待所有agent协程退出 switch msg { case syscall.SIGTERM: //关闭agent close(die) log.Info("sigterm received") log.Info("waiting for agents close, please wait...") wg.Wait() log.Info("agent shutdown.") os.Exit(0) } } }
//游戏入口 func main() { defer utils.PrintPanicStack() go func() { log.Info(http.ListenAndServe("0.0.0.0:6060", nil)) }() log.SetPrefix(SERVICE) tcpAddr, err := net.ResolveTCPAddr("tcp4", _port) checkError(err) listener, err := net.ListenTCP("tcp", tcpAddr) checkError(err) log.Info("listening on:", listener.Addr()) // loop accepting for { conn, err := listener.AcceptTCP() if err != nil { log.Warning("accept failed:", err) continue } go handleClient(conn) // check server close signal select { case <-die: listener.Close() goto FINAL default: } } FINAL: // server closed, wait forever // 此处为什么要等1秒 // 此处等待1秒钟,只是为了wg.Wait() 可以执行到,从而阻塞主线程 for { <-time.After(time.Second) } }
// background loader, copy chan into map, execute dump every SAVE_DELAY func (s *server) loader_task() { dirty := make(map[string]bool) timer := time.After(SAVE_DELAY) timer_count := time.After(COUNT_DELAY) sig := make(chan os.Signal, 1) signal.Notify(sig, syscall.SIGTERM) //记录处理的个数 var count uint64 for { select { case key := <-s.wait: dirty[key] = true case <-timer: if len(dirty) > 0 { //计数 count += uint64(len(dirty)) //写入 s.dump(dirty) //清空 dirty = make(map[string]bool) } //重新计时 timer = time.After(SAVE_DELAY) case <-timer_count: //打印计数 log.Info("num records saved:", count) timer_count = time.After(COUNT_DELAY) case <-sig: //当有关闭信号发送时 if len(dirty) > 0 { s.dump(dirty) } log.Info("SIGTERM") os.Exit(0) } } }
func init() { go func() { // padding content update procedure for { for k := range _padding { //利用快速生成器填充内容 //生成32位,填充只有后8位,丢失3字节精度 _padding[k] = byte(<-utils.LCG) } log.Info("Padding Updated:", _padding) // 300秒更新一次填充值 <-time.After(PADDING_UPDATE_PERIOD * time.Second) } }() }
func main() { log.SetPrefix(SERVICE) lis, err := net.Listen("tcp", _port) if err != nil { log.Critical(err) os.Exit(-1) } log.Info("listenin on ", lis.Addr()) s := grpc.NewServer() ins := &server{} ins.init() pb.RegisterChatServiceServer(s, ins) s.Serve(lis) }
//持久化任务 func (s *server) persistence_task() { //一分钟执行一次 timer := time.After(CHECK_INTERVAL) db := s.open_db() //定义改变的id集合 changes := make(map[uint64]bool) //信号监听 sig := make(chan os.Signal, 1) signal.Notify(sig, syscall.SIGTERM, syscall.SIGINT) for { select { //s.pending传入变更的id case key := <-s.pending: changes[key] = true case <-timer: //一分钟后写入 s.dump(db, changes) log.Infof("perisisted %v endpoints:", len(changes)) //清空 changes = make(map[uint64]bool) //重新计时 timer = time.After(CHECK_INTERVAL) //当接受关闭信号时 case nr := <-sig: //写入数据 s.dump(db, changes) //关闭 db.Close() log.Info(nr) os.Exit(0) } } }