Пример #1
0
func NewServer(addr string, debugVarAddr string, conf *Conf) *Server {
	log.Infof("%+v", conf)
	s := &Server{
		evtbus:            make(chan interface{}, 100),
		top:               topo.NewTopo(conf.productName, conf.zkAddr, conf.f),
		net_timeout:       conf.net_timeout,
		counter:           stats.NewCounters("router"),
		lastActionSeq:     -1,
		startAt:           time.Now(),
		addr:              addr,
		concurrentLimiter: tokenlimiter.NewTokenLimiter(100),
		moper:             NewMultiOperator(addr),
		pools:             cachepool.NewCachePool(),
	}

	s.broker = conf.broker

	slot_num = conf.slot_num

	s.mu.Lock()
	s.pi.Id = conf.proxyId
	s.pi.State = models.PROXY_STATE_OFFLINE
	hname, err := os.Hostname()
	if err != nil {
		log.Fatal("get host name failed", err)
	}
	s.pi.Addr = hname + ":" + strings.Split(addr, ":")[1]
	s.pi.DebugVarAddr = hname + ":" + strings.Split(debugVarAddr, ":")[1]
	log.Infof("proxy_info:%+v", s.pi)
	s.mu.Unlock()
	//todo:fill more field

	stats.Publish("evtbus", stats.StringFunc(func() string {
		return strconv.Itoa(len(s.evtbus))
	}))
	stats.Publish("startAt", stats.StringFunc(func() string {
		return s.startAt.String()
	}))

	s.RegisterAndWait()

	_, err = s.top.WatchChildren(models.GetWatchActionPath(conf.productName), s.evtbus)
	if err != nil {
		log.Fatal(errors.ErrorStack(err))
	}

	s.FillSlots()

	//start event handler
	go s.handleTopoEvent()

	log.Info("proxy start ok")

	return s
}
Пример #2
0
func (top *Topology) GetActionResponsePath(seq int) string {
	return path.Join(models.GetWatchActionPath(top.ProductName), "action_"+fmt.Sprintf("%0.10d", seq))
}
Пример #3
0
func (s *Server) processAction(e interface{}) {
	start := time.Now()
	s.mu.Lock()
	defer s.mu.Unlock()

	if time.Since(start).Seconds() > 10 {
		log.Warning("take too long to get lock")
	}

	actPath := GetEventPath(e)
	if strings.Index(actPath, models.GetProxyPath(s.top.ProductName)) == 0 {
		//proxy event, should be order for me to suicide
		s.handleProxyCommand()
		return
	}

	//re-watch
	nodes, err := s.top.WatchChildren(models.GetWatchActionPath(s.top.ProductName), s.evtbus)
	if err != nil {
		log.Fatal(errors.ErrorStack(err))
	}

	seqs, err := models.ExtraSeqList(nodes)
	if err != nil {
		log.Fatal(errors.ErrorStack(err))
	}

	if len(seqs) == 0 || !s.top.IsChildrenChangedEvent(e) {
		return
	}

	//get last pos
	index := -1
	for i, seq := range seqs {
		if s.lastActionSeq < seq {
			index = i
			break
		}
	}

	if index < 0 {
		log.Warningf("zookeeper restarted or actions were deleted ? lastActionSeq: %d", s.lastActionSeq)
		if s.lastActionSeq > seqs[len(seqs)-1] {
			log.Fatalf("unknown error, zookeeper restarted or actions were deleted ? lastActionSeq: %d, %v", s.lastActionSeq, nodes)
		}

		if s.lastActionSeq == seqs[len(seqs)-1] { //children change or delete event
			return
		}

		//actions node was remove by someone, seems we can handle it
		index = 0
	}

	actions := seqs[index:]
	for _, seq := range actions {
		exist, err := s.top.Exist(path.Join(s.top.GetActionResponsePath(seq), s.pi.Id))
		if err != nil {
			log.Fatal(errors.ErrorStack(err))
		}

		if exist {
			continue
		}

		if s.checkAndDoTopoChange(seq) {
			s.responseAction(int64(seq))
		}
	}

	s.lastActionSeq = seqs[len(seqs)-1]
}
Пример #4
0
func InitEnv() {
	go once.Do(func() {
		conn = zkhelper.NewConn()
		conf = &Conf{
			proxyId:     "proxy_test",
			productName: "test",
			zkAddr:      "localhost:2181",
			net_timeout: 5,
			f:           func(string) (zkhelper.Conn, error) { return conn, nil },
			slot_num:    16,
			//broker:      LedisBroker,
		}

		//init action path
		prefix := models.GetWatchActionPath(conf.productName)
		err := models.CreateActionRootPath(conn, prefix)
		if err != nil {
			log.Fatal(err)
		}

		//init slot
		err = models.InitSlotSet(conn, conf.productName, conf.slot_num)
		if err != nil {
			log.Fatal(err)
		}

		//init  server group
		g1 := models.NewServerGroup(conf.productName, 1)
		g1.Create(conn)
		g2 := models.NewServerGroup(conf.productName, 2)
		g2.Create(conn)

		redis1, _ := miniredis.Run()
		redis2, _ := miniredis.Run()

		s1 := models.NewServer(models.SERVER_TYPE_MASTER, redis1.Addr())
		s2 := models.NewServer(models.SERVER_TYPE_MASTER, redis2.Addr())

		g1.AddServer(conn, s1)
		g2.AddServer(conn, s2)

		//set slot range
		err = models.SetSlotRange(conn, conf.productName, 0, conf.slot_num/2-1, 1, models.SLOT_STATUS_ONLINE)
		if err != nil {
			log.Fatal(err)
		}

		err = models.SetSlotRange(conn, conf.productName, conf.slot_num/2, conf.slot_num-1, 2, models.SLOT_STATUS_ONLINE)
		if err != nil {
			log.Fatal(err)
		}

		go func() { //set proxy online
			time.Sleep(5 * time.Second)
			err := models.SetProxyStatus(conn, conf.productName, conf.proxyId, models.PROXY_STATE_ONLINE)
			if err != nil {
				log.Fatal(errors.ErrorStack(err))
			}
			time.Sleep(2 * time.Second)
			proxyMutex.Lock()
			defer proxyMutex.Unlock()
			pi := s.getProxyInfo()
			if pi.State != models.PROXY_STATE_ONLINE {
				log.Fatalf("should be online, we got %s", pi.State)
			}
		}()

		proxyMutex.Lock()
		s = NewServer(":19000", ":11000",
			conf,
		)
		proxyMutex.Unlock()
		s.Run()
	})

	waitonce.Do(func() {
		time.Sleep(10 * time.Second)
	})
}