Exemplo n.º 1
0
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{})
	serviceEndpoint := RegisterService(p.serviceName, p.frontendAddr, p.lbServiceName,
		p.topo, evtExit, p.config.WorkDir, p.config.CodeUrlVersion)

	//	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 FileExist(p.frontendAddr) {
			os.Remove(p.frontendAddr)
		}
		transport, err = 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)

	// 强制退出? 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.(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
		}
	}
}
Exemplo n.º 2
0
func (s *BackServiceLB) run() {
	go func() {
		// 定时汇报当前的状态
		for true {
			log.Printf(Green("[Report]: %s --> %d workers, coroutine: %d"),
				s.serviceName, s.Active(), runtime.NumGoroutine())
			time.Sleep(time.Second * 10)
		}
	}()

	var transport thrift.TServerTransport
	var err error

	// 3. 读取后端服务的配置
	isUnixDomain := false
	// 127.0.0.1:9999(以:区分不同的类型)
	if !strings.Contains(s.backendAddr, ":") {
		if FileExist(s.backendAddr) {
			os.Remove(s.backendAddr)
		}
		transport, err = NewTServerUnixDomain(s.backendAddr)
		isUnixDomain = true
	} else {
		transport, err = thrift.NewTServerSocket(s.backendAddr)
	}

	if err != nil {
		log.ErrorErrorf(err, "[%s]Server Socket Create Failed: %v", s.serviceName, err)
		panic("BackendAddr Invalid")
	}

	err = transport.Listen()
	if err != nil {
		log.ErrorErrorf(err, "[%s]Server Socket Open Failed: %v", s.serviceName, err)
		panic("Server Socket Open Failed")
	}

	// 和transport.open做的事情一样,如果Open没错,则Listen也不会有问题

	log.Printf(Green("[%s]LB Backend Services listens at: %s"), s.serviceName, s.backendAddr)

	s.ch = make(chan thrift.TTransport, 4096)

	// 强制退出? TODO: Graceful退出
	go func() {
		<-s.exitEvt
		log.Info(Red("Receive Exit Signals...."))
		transport.Interrupt()
		transport.Close()
	}()

	go func() {
		var backendAddr string
		for trans := range s.ch {
			// 为每个Connection建立一个Session
			socket, ok := trans.(SocketAddr)
			if ok {
				if isUnixDomain {
					backendAddr = s.backendAddr
				} else {
					backendAddr = socket.Addr().String()
				}

				conn := NewBackendConnLB(trans, s.serviceName, backendAddr, s, s.verbose)

				// 因为连接刚刚建立,可靠性还是挺高的,因此直接加入到列表中
				s.activeConnsLock.Lock()
				conn.Index = len(s.activeConns)
				s.activeConns = append(s.activeConns, conn)
				s.activeConnsLock.Unlock()

				log.Printf(Green("%s --> %d workers"), s.serviceName, conn.Index)
			} else {
				panic("Invalid Socket Type")
			}

		}
	}()

	// Accept什么时候出错,出错之后如何处理呢?
	go func() {
		for {
			c, err := transport.Accept()
			if err != nil {
				return
			} else {
				s.ch <- c
			}
		}
	}()
}