func (p *ThriftRpcServer) Run() { // // 1. 创建到zk的连接 p.Topo = NewTopology(p.ProductName, p.ZkAddr) // 127.0.0.1:5555 --> 127_0_0_1:5555 lbServiceName := GetServiceIdentity(p.FrontendAddr) exitSignal := make(chan os.Signal, 1) signal.Notify(exitSignal, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL) // syscall.SIGKILL // kill -9 pid // kill -s SIGKILL pid 还是留给运维吧 StartTicker(p.config.FalconClient, p.ServiceName) // 初始状态为不上线 var state atomic2.Bool state.Set(false) stateChan := make(chan bool) // 注册服务 evtExit := make(chan interface{}) endpoint := RegisterService(p.ServiceName, p.FrontendAddr, lbServiceName, p.Topo, evtExit, p.config.WorkDir, p.config.CodeUrlVersion, &state, stateChan) // 3. 读取"前端"的配置 var transport thrift.TServerTransport var err error isUnixDomain := false // 127.0.0.1:9999(以:区分不同的类型) if !strings.Contains(p.FrontendAddr, ":") { if rpc_utils.FileExist(p.FrontendAddr) { os.Remove(p.FrontendAddr) } transport, err = rpc_utils.NewTServerUnixDomain(p.FrontendAddr) isUnixDomain = true } else { transport, err = thrift.NewTServerSocket(p.FrontendAddr) } if err != nil { log.ErrorErrorf(err, Red("Server Socket Create Failed: %v"), err) panic(fmt.Sprintf("Invalid FrontendAddr: %s", p.FrontendAddr)) } err = transport.Listen() if err != nil { log.ErrorErrorf(err, Red("Server Socket Open Failed: %v"), err) panic(fmt.Sprintf("Server Socket Open Failed: %s", p.FrontendAddr)) } ch := make(chan thrift.TTransport, 4096) defer close(ch) // 强制退出? TODO: Graceful退出 go func() { <-exitSignal evtExit <- true log.Info(Magenta("Receive Exit Signals....")) endpoint.DeleteServiceEndpoint(p.Topo) // 等待 start := time.Now().Unix() for true { // 如果5s内没有接受到新的请求了,则退出 now := time.Now().Unix() if now-p.lastRequestTime.Get() > 5 { log.Info(Red("Graceful Exit...")) break } else { log.Printf(Cyan("Sleeping %d seconds\n"), now-start) time.Sleep(time.Second) } } transport.Interrupt() transport.Close() }() go func() { var address string for c := range ch { // 为每个Connection建立一个Session socket, ok := c.(rpc_utils.SocketAddr) if ok { if isUnixDomain { address = p.FrontendAddr } else { address = socket.Addr().String() } } else { address = "unknow" } x := NewNonBlockSession(c, address, p.Verbose, &p.lastRequestTime) // Session独立处理自己的请求 go x.Serve(p, 1000) } }() // 准备上线服务 state.Set(true) stateChan <- true // Accept什么时候出错,出错之后如何处理呢? for { c, err := transport.Accept() if err != nil { break } else { ch <- c } } }
// // 去ZK注册当前的Service // func RegisterService(serviceName, frontendAddr, serviceId string, topo *Topology, evtExit chan interface{}, workDir string, codeUrlVerion string, state *atomic2.Bool, stateChan chan bool) *ServiceEndpoint { // 1. 准备数据 // 记录Service Endpoint的信息 servicePath := topo.ProductServicePath(serviceName) // 确保东西存在 if ok, _ := topo.Exist(servicePath); !ok { topo.CreateDir(servicePath) } // 用来从zookeeper获取事件 evtbus := make(chan interface{}) // 2. 将信息添加到Zk中, 并且监控Zk的状态(如果添加失败会怎么样?) endpoint := NewServiceEndpoint(serviceName, serviceId, frontendAddr, workDir, codeUrlVerion) // deployPath // 为了保证Add是干净的,需要先删除,保证自己才是Owner endpoint.DeleteServiceEndpoint(topo) // 如果没有状态,或状态为true, 则上线 if state == nil || state.Get() { endpoint.AddServiceEndpoint(topo) } go func() { for true { // Watch的目的是监控: 当前的zk session的状态, 如果session出现异常,则重新注册 _, err := topo.WatchNode(servicePath, evtbus) if err == nil { // 如果成功添加Watch, 则等待退出,或者ZK Event select { case <-evtExit: return case <-stateChan: // 如何状态变化(则重新注册) endpoint.DeleteServiceEndpoint(topo) if state == nil || state.Get() { endpoint.AddServiceEndpoint(topo) } case e := <-evtbus: event := e.(topozk.Event) if event.State == topozk.StateExpired || event.Type == topozk.EventNotWatching { // Session过期了,则需要删除之前的数据, // 因为当前的session不是之前的数据的Owner endpoint.DeleteServiceEndpoint(topo) if state == nil || state.Get() { endpoint.AddServiceEndpoint(topo) } } } } else { // 如果添加Watch失败,则等待退出,或等待timer接触,进行下一次尝试 timer := time.NewTimer(time.Second * time.Duration(10)) log.ErrorErrorf(err, "Reg Failed, Wait 10 seconds...., %v", err) select { case <-evtExit: return case <-timer.C: // pass } } } }() return endpoint }
func (p *ThriftLoadBalanceServer) Run() { // // 1. 创建到zk的连接 // 127.0.0.1:5555 --> 127_0_0_1:5555 exitSignal := make(chan os.Signal, 1) signal.Notify(exitSignal, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL) // syscall.SIGKILL // kill -9 pid // kill -s SIGKILL pid 还是留给运维吧 // // 注册服务 evtExit := make(chan interface{}) // 初始状态为不上线 var state atomic2.Bool state.Set(false) stateChan := make(chan bool) serviceEndpoint := RegisterService(p.serviceName, p.frontendAddr, p.lbServiceName, p.topo, evtExit, p.config.WorkDir, p.config.CodeUrlVersion, &state, stateChan) // var suideTime time.Time // isAlive := true // 3. 读取后端服务的配置 var transport thrift.TServerTransport var err error isUnixDomain := false // 127.0.0.1:9999(以:区分不同的类型) if !strings.Contains(p.frontendAddr, ":") { if rpc_utils.FileExist(p.frontendAddr) { os.Remove(p.frontendAddr) } transport, err = rpc_utils.NewTServerUnixDomain(p.frontendAddr) isUnixDomain = true } else { transport, err = thrift.NewTServerSocket(p.frontendAddr) } if err != nil { log.ErrorErrorf(err, "Server Socket Create Failed: %v", err) panic(fmt.Sprintf("Invalid FrontendAddress: %s", p.frontendAddr)) } err = transport.Listen() if err != nil { log.ErrorErrorf(err, "Server Socket Create Failed: %v", err) panic(fmt.Sprintf("Binding Error FrontendAddress: %s", p.frontendAddr)) } ch := make(chan thrift.TTransport, 4096) defer close(ch) // 等待后端服务起来 waitTicker := time.NewTicker(time.Second) // 等待上线采用的策略: // 1. 检测到有效的Worker注册之后,再等5s即可像zk注册; 避免了Worker没有连接上来,就有请求过来 // 2. 一旦注册之后,就不再使用该策略;避免服务故障时,lb频繁更新zk, 导致proxy等频繁读取zk START_WAIT: for true { select { case <-waitTicker.C: if p.backendService.Active() <= 0 { log.Infof("Sleep Waiting for back Service to Start") time.Sleep(time.Second) } else { break START_WAIT } case <-exitSignal: // 直接退出 transport.Interrupt() transport.Close() return } } log.Infof("Stop Waiting") // 停止: waitTicker, 再等等就继续了 waitTicker.Stop() time.Sleep(time.Second * 5) log.Infof("Begin to Reg To Zk...") state.Set(true) stateChan <- true // 强制退出? TODO: Graceful退出 go func() { <-exitSignal // 通知RegisterService终止循环 evtExit <- true log.Info(Green("Receive Exit Signals....")) serviceEndpoint.DeleteServiceEndpoint(p.topo) start := time.Now().Unix() for true { // 如果5s内没有接受到新的请求了,则退出 now := time.Now().Unix() if now-p.lastRequestTime.Get() > 5 { log.Printf(Red("[%s]Graceful Exit..."), p.serviceName) break } else { log.Printf(Cyan("[%s]Sleeping %d seconds before Exit...\n"), p.serviceName, now-start) time.Sleep(time.Second) } } transport.Interrupt() transport.Close() }() go func() { var address string for c := range ch { // 为每个Connection建立一个Session socket, ok := c.(rpc_utils.SocketAddr) if ok { if isUnixDomain { address = p.frontendAddr } else { address = socket.Addr().String() } } else { address = "unknow" } x := NewNonBlockSession(c, address, p.verbose, &p.lastRequestTime) // Session独立处理自己的请求 go x.Serve(p.backendService, 1000) } }() // Accept什么时候出错,出错之后如何处理呢? for { c, err := transport.Accept() if err != nil { close(ch) break } else { ch <- c } } }