示例#1
0
// AddNode add a node and watch it, and notice Comet to migrate node
func AddNode(node string) error {
	_, ok := NodeInfoMap[node]
	if ok {
		return ErrNodeExist
	}

	var nodes []string
	for n, _ := range NodeInfoMap {
		nodes = append(nodes, n)
	}

	nodes = append(nodes, node)

	// Notice Comet to migrate node
	if err := channelRPCMigrate(nodes, NodeInfoMap); err != nil {
		return err
	}

	// Watch the node
	go watchFirstService(node)

	// Update Comet hash, because of nodes are changed
	CometHash = hash.NewKetama2(nodes, 255)

	return nil
}
示例#2
0
// AddNode add a node and watch it
func AddNode(node string) error {
	NodeInfoMapLock.RLock()
	defer NodeInfoMapLock.RUnlock()
	_, ok := NodeInfoMap[node]
	if ok {
		return ErrNodeExist
	}

	var nodes []string
	for n, _ := range NodeInfoMap {
		nodes = append(nodes, n)
	}

	nodes = append(nodes, node)

	// Notice comet to migrate node
	if err := ChannelRPCMigrate(nodes, NodeInfoMap); err != nil {
		return err
	}

	go watchFirstServer(node)

	CometHash = hash.NewKetama2(nodes, 255)

	return nil
}
示例#3
0
// DelNode disconnect and delete a node
func DelNode(node string) error {
	var (
		nodes []string
		info  *NodeInfo
	)
	NodeInfoMapLock.Lock()
	defer NodeInfoMapLock.Unlock()
	for n, c := range NodeInfoMap {
		if n == node {
			info = c
			continue
		}

		nodes = append(nodes, n)
	}

	CometHash = hash.NewKetama2(nodes, 255)

	delete(NodeInfoMap, node)

	if info != nil && info.PubRPC != nil {
		info.PubRPC.Close()
		info.PubRPC = nil
	}

	// Notice comet to migrate node
	if err := ChannelRPCMigrate(nodes, NodeInfoMap); err != nil {
		return err
	}

	return nil
}
示例#4
0
// BeginWatchNode start watch all of nodes
func BeginWatchNode() error {
	nodes, err := getNodes(Conf.Zookeeper.RootPath)
	if err != nil {
		return err
	}

	CometHash = hash.NewKetama2(nodes, 255)
	watchNodes(nodes)

	return nil
}
示例#5
0
// Publish expored a method for publishing a message for the channel
func (c *ChannelRPC) Migrate(args *myrpc.ChannelMigrateArgs, ret *int) error {
	if len(args.Nodes) == 0 {
		*ret = myrpc.ParamErr
		return nil
	}
	// find current node exists in new nodes
	has := false
	for _, str := range args.Nodes {
		if str == Conf.ZookeeperNode {
			has = true
		}
	}
	if !has {
		Log.Crit("make sure your migrate nodes right, there is no %s in nodes, this will cause all the node hit miss", Conf.ZookeeperNode)
		*ret = myrpc.MigrateErr
		return nil
	}
	// init ketama
	ketama := hash.NewKetama2(args.Nodes, args.Vnode)
	channels := []Channel{}
	keys := []string{}
	// get all the channel lock
	for i, c := range UserChannel.Channels {
		c.Lock()
		for k, v := range c.Data {
			hn := ketama.Node(k)
			if hn != Conf.ZookeeperNode {
				channels = append(channels, v)
				keys = append(keys, k)
				Log.Debug("migrate key:\"%s\" hit node:\"%s\"", k, hn)
			}
		}
		for _, k := range keys {
			delete(c.Data, k)
			Log.Info("migrate delete channel key \"%s\"", k)
		}
		c.Unlock()
		Log.Info("migrate channel bucket:%d finished", i)
	}
	// close all the migrate channels
	Log.Info("close all the migrate channels")
	for _, channel := range channels {
		if err := channel.Close(); err != nil {
			Log.Error("channel.Close() error(%v)", err)
			continue
		}
	}
	*ret = myrpc.OK
	Log.Info("close all the migrate channels finished")
	return nil
}
示例#6
0
// BeginWatchNode start watch all of nodes which registered in zookeeper
func BeginWatchNode() error {
	nodes, err := getNodes(Conf.ZKCometPath)
	if err != nil {
		Log.Error("getNodes(\"%s\") error(%v)", Conf.ZKCometPath, err)
		return err
	}

	// Update Comet hash, cause nodes are changed
	CometHash = hash.NewKetama2(nodes, 255)

	// Watch all of nodes
	watchNodes(nodes)

	return nil
}
示例#7
0
// BeginWatchNode start watch all of nodes which registered in zookeeper
func BeginWatchNode() error {
	nodes, err := getNodes(Conf.ZKCometPath)
	if err != nil {
		Log.Error("getNodes(\"%s\") error(%v)", Conf.ZKCometPath, err)
		return err
	}

	for _, n := range nodes {
		NodeInfoMap[n] = nil
	}

	// Update Comet hash
	CometHash = hash.NewKetama2(nodes, 255)
	// Watch all of nodes
	watchNodes(nodes)

	return nil
}
示例#8
0
// DelNode disconnect and delete a node, and notice Comet to migrate node
func DelNode(node string) error {
	var (
		nodes []string
		info  *NodeInfo
	)

	if _, ok := NodeInfoMap[node]; !ok {
		return nil
	}

	for n, c := range NodeInfoMap {
		if n == node {
			info = c
			continue
		}

		nodes = append(nodes, n)
	}

	// Update Comet hash, cause nodes are changed
	CometHash = hash.NewKetama2(nodes, 255)

	// Delete node from map before call Migrate RPC interface of Comet, cause needn`t to notice deleted node
	tmpMap := make(map[string]*NodeInfo)
	for n, i := range NodeInfoMap {
		tmpMap[n] = i
	}
	delete(tmpMap, node)
	NodeInfoMap = tmpMap

	if info != nil && info.PubRPC != nil {
		info.PubRPC.Close()
	}

	// Notice Comet to migrate node
	if err := channelRPCMigrate(nodes, NodeInfoMap); err != nil {
		return err
	}

	return nil
}
示例#9
0
// handleNodeEvent add and remove NodeInfo, copy the src map to a new map then replace the variable.
func handleNodeEvent(conn *zk.Conn, path string, ch chan *NodeEvent) {
	for {
		ev := <-ch
		// copy map from src
		tmpMap := make(map[string]*NodeInfo, len(NodeInfoMap))
		for k, v := range NodeInfoMap {
			tmpMap[k] = v
		}
		// handle event
		if ev.Event == EventNodeAdd {
			Log.Info("add node: \"%s\"", ev.Key)
			tmpMap[ev.Key] = nil
			go watchNode(conn, ev.Key, path, ch)
		} else if ev.Event == EventNodeDel {
			Log.Info("del node: \"%s\"", ev.Key)
			delete(tmpMap, ev.Key)
		} else if ev.Event == EventNodeUpdate {
			Log.Info("update node: \"%s\"", ev.Key)
			tmpMap[ev.Key] = ev.Value
		} else {
			Log.Crit("unknown node event: %d", ev.Event)
			panic("unknown node event")
		}
		// if exist old node info, close
		if info, ok := NodeInfoMap[ev.Key]; ok {
			if info != nil {
				info.Close()
				Log.Info("close old node info: \"%s\"", ev.Key)
			}
		}
		// use the tmpMap atomic replace the global NodeInfoMap
		NodeInfoMap = tmpMap
		// update comet hash, cause node has changed
		nodes := make([]string, 0, len(tmpMap))
		for k, _ := range tmpMap {
			nodes = append(nodes, k)
		}
		cometHash = hash.NewKetama2(nodes, 255)
		Log.Debug("NodeInfoMap len: %d", len(NodeInfoMap))
	}
}
示例#10
0
// handleCometNodeEvent add and remove CometNodeInfo, copy the src map to a new map then replace the variable.
func handleCometNodeEvent(conn *zk.Conn, fpath string, retry, ping time.Duration, ch chan *CometNodeEvent) {
	for {
		ev := <-ch
		// copy map from src
		tmpMap := make(map[string]*CometNodeInfo, len(cometNodeInfoMap))
		for k, v := range cometNodeInfoMap {
			tmpMap[k] = v
		}
		// handle event
		if ev.Event == eventNodeAdd {
			glog.Infof("add node: \"%s\"", ev.Key)
			tmpMap[ev.Key] = nil
			go watchCometNode(conn, ev.Key, fpath, retry, ping, ch)
		} else if ev.Event == eventNodeDel {
			glog.Infof("del node: \"%s\"", ev.Key)
			delete(tmpMap, ev.Key)
		} else if ev.Event == eventNodeUpdate {
			glog.Infof("update node: \"%s\"", ev.Key)
			tmpMap[ev.Key] = ev.Value
		} else {
			glog.Errorf("unknown node event: %d", ev.Event)
			panic("unknown node event")
		}
		// if exist old node info, destroy
		if info, ok := cometNodeInfoMap[ev.Key]; ok {
			if info != nil {
				info.CometRPC.Destroy()
			}
		}
		// use the tmpMap atomic replace the global cometNodeInfoMap
		cometNodeInfoMap = tmpMap
		// update comet hash, cause node has changed
		nodes := make([]string, 0, len(tmpMap))
		for k, _ := range tmpMap {
			nodes = append(nodes, k)
		}
		cometHash = hash.NewKetama2(nodes, 255)
		glog.V(1).Infof("cometNodeInfoMap len: %d", len(cometNodeInfoMap))
	}
}
示例#11
0
// watchNodes watch the first service under the node, and keep rpc connecting with Comet RPC,
// the first service must be alive
func watchFirstService(node string) {
	defer func() {
		if err := recover(); err != nil {
			Log.Error("watching node goroutine panic node:\"%s\" error(%v), stop watching", node, err)

			var nodes []string
			// Delete node from map
			tmpMap := make(map[string]*NodeInfo)
			for n, i := range NodeInfoMap {
				if n == node {
					continue
				}
				tmpMap[n] = i
				nodes = append(nodes, n)
			}
			NodeInfoMap = tmpMap

			// Update Comet hash, cause node has changed
			CometHash = hash.NewKetama2(nodes, 255)
		}
	}()
	path := fmt.Sprintf("%s/%s", Conf.ZKCometPath, node)
	for {
		subNodes, watch, err := getNodesW(path)
		if err != nil {
			// If no subNode, then check repeatedly
			if err == ErrNoChild {
				Log.Warn("get service of node:\"%s\" error(%v), recheck after 5 seconds", node, err)
				time.Sleep(5 * time.Second)
				continue
			}

			Log.Error("get service of node:\"%s\" error(%v), stop watching", node, err)
			break
		}

		// Get service infomation
		sort.Strings(subNodes)
		data, _, err := zk.Get(fmt.Sprintf("%s/%s", path, subNodes[0]))
		if err != nil {
			Log.Error("watch node:\"%s\", subNode:\"%s\", error(%v)", node, subNodes[0], err)
			time.Sleep(5 * time.Second)
			continue
		}

		// Fecth and parse push service connection info
		subAddr, err := parseZKData(data)
		if err != nil {
			Log.Error("get subNode data error node:\"%s\", subNode:\"%s\", error(%v)", node, subNodes[0], err)
			time.Sleep(5 * time.Second)
			continue
		}
		info := NodeInfoMap[node]
		if info != nil {
			info.SubAddr = subAddr
			if info.PubRPC != nil {
				info.PubRPC.Close()
			}
		} else {
			info = &NodeInfo{SubAddr: subAddr}
		}
		tmpMap := make(map[string]*NodeInfo)
		for n, i := range NodeInfoMap {
			tmpMap[n] = i
		}
		tmpMap[node] = info
		NodeInfoMap = tmpMap
		// ReDial RPC
		addr, ok := subAddr[ProtocolRPC]
		if ok {
			r, err := rpc.Dial("tcp", addr)
			if err != nil {
				Log.Error("rpc.Dial(\"tcp\", \"%s\") error(%v) node:\"%s\", subNode:\"%s\", recheck after 5 seconds", addr, err, node, subNodes[0])
				time.Sleep(5 * time.Second)
				continue
			}

			info.PubRPC = r
		} else {
			Log.Error("rpc.Dial(\"tcp\", \"%s\") error node:\"%s\", subNode:\"%s\" error(no rpc address)", addr, node, subNodes[0])
		}

		Log.Info("begin watching node:\"%s\" addr:\"%v\"", node, subAddr)
		event := <-watch
		Log.Warn("end watching node:\"%s\" addr:\"%v\" event:\"%v\", retry to watch", node, subAddr, event)
	}

	// Delete node
	Log.Warn("stop watching node:\"%s\"", node)
	if err := DelNode(node); err != nil {
		Log.Error("stop watching node:\"%s\" error(%v)", node, err)
		return
	}
}