discovery service for golang
注意:目前对etcd watch方式做下测试,效果不是很理想。本库慎用与生产环境!!!
后续会对 go-discovery 实现机制做回炉改造!!!
- 封装etcd,提供事件触发接口
- 节点自识别自身对外IP
- 节点自动分配可用端口、多节点不会冲突
- 自动分配节点ID、多节点ID不会冲突
- 提供服务列表
type MyNode struct {
godiscovery.Node
}
func NewMyNode() *MyNode {
this := &MyNode{}
this.Node.Init(this)
return this
}
func (this *MyNode) OnNodeUpdate(nodeIP string, nodeType int, id uint32, data []byte) {
fmt.Println("OnNodeUpdate: nodeIP =", nodeIP, "nodeType =", nodeType, "id =", id, "data =", string(data))
}
func (this *MyNode) OnNodeJoin(nodeIP string, nodeType int, id uint32, data []byte) {
fmt.Println("OnNodeJoin: nodeIP =", nodeIP, "nodeType =", nodeType, "id =", id, "data =", string(data))
}
func (this *MyNode) OnNodeLeave(nodeType int, id uint32) {
fmt.Println("OnNodeLeave: nodeType =", nodeType, "id =", id)
}
func (this *MyNode) GetPutData() (string, error) {
return string("here can put overload data!"), nil
}
func main() {
hosts := ""
flag.StringVar(&hosts, "hosts", "101.132.47.70:12379,101.132.47.70:22379,101.132.47.70:32379", "etcd hosts")
whatsmyip := ""
flag.StringVar(&whatsmyip, "whatsmyip", "101.132.47.70:3000", "whatsmyip host")
nodeType := 0
flag.IntVar(&nodeType, "nodeType", 1, "node type")
watchNodeTypes := ""
flag.StringVar(&watchNodeTypes, "watchNodeTypes", "1,2,3,4", "watch node type")
putInterval := int64(0)
flag.Int64Var(&putInterval, "putInterval", 1, "put interval")
flag.Parse()
node := NewMyNode()
node.OpenByStr(hosts, whatsmyip, nodeType, watchNodeTypes, putInterval)
for {
time.Sleep(time.Minute)
}
}
-
hosts
etcd 地址列表
-
whatsmyip
whatsmyip 地址
-
nodeType
自己节点的类型,非0,则定期(putInterval)调用GetPutData函数,上传数据
-
watchNodeTypes
要监听的节点类型列表。非空,则OnNodeUpdate、OnNodeJoin、OnNodeLeave会被触发
-
putInterval
调用GetPutData函数的频率,单位秒
获取服务列表
需要import的代码在 github.com/fananchong/go-discovery/serverlist
func NewMyNode() *MyNode {
this := &MyNode{}
this.Node = discovery.NewDefaultNode(this)
return this
}
func (this *MyNode) OnNodeJoin(nodeIP string, nodeType int, id uint32, data []byte) {
this.Node.OnNodeJoin(nodeIP, nodeType, id, data)
fmt.Println("print current all node:")
for t := 1; t <= 4; t++ {
if lst, ok := this.Servers.GetAll(t); ok {
for _, info := range lst {
fmt.Printf(" id:%d type:%d addr:%s\n", info.GetId(), info.GetType(), info.GetExternalIp())
}
}
}
}
func (this *MyNode) OnNodeLeave(nodeType int, id uint32) {
this.Node.OnNodeLeave(nodeType, id)
fmt.Println("print current all node:")
for t := 1; t <= 4; t++ {
if lst, ok := this.Servers.GetAll(t); ok {
for _, info := range lst {
fmt.Printf(" id:%d type:%d addr:%s\n", info.GetId(), info.GetType(), info.GetExternalIp())
}
}
}
}
func main() {
hosts := ""
flag.StringVar(&hosts, "hosts", "101.132.47.70:12379,101.132.47.70:22379,101.132.47.70:32379", "etcd hosts")
whatsmyip := ""
flag.StringVar(&whatsmyip, "whatsmyip", "101.132.47.70:3000", "whatsmyip host")
nodeType := 0
flag.IntVar(&nodeType, "nodeType", 1, "node type")
watchNodeTypes := ""
flag.StringVar(&watchNodeTypes, "watchNodeTypes", "1,2,3,4", "watch node type")
putInterval := int64(0)
flag.Int64Var(&putInterval, "putInterval", 1, "put interval")
flag.Parse()
node := NewMyNode()
node.OpenByStr(hosts, whatsmyip, nodeType, watchNodeTypes, putInterval)
for {
time.Sleep(10 * time.Second)
}
node.Close()
}
OnNodeUpdate、OnNodeJoin、OnNodeLeave、GetPutData 在内部协程被调用,请注意多协程安全!!!
经测试,etcd不能频繁put数据,可以通过优化操作:
- 进程开启时,put一次数据
- 超过负载或恢复正常时,put一次数据
- 60s,定期,put数据 (看服务节点数据,来调整)
客户端做轮询方式负载均衡
这样可以极大的减轻etcd的负载
提供2种Docker Swarm方式部署etcd
启动脚本 | 说明 |
---|---|
docker-swarm/install-etcd-static.sh | 静态配置方式部署etcd |
docker-swarm/install-discovery.etcd.io.sh docker-swarm/install-etcd.sh |
etcd发现方式部署etcd |
启动脚本 | 说明 |
---|---|
docker-swarm/install-whatsmyip.sh | 启动whatsmyip服务 |