etcd服务发现

etcd注册模块是如何保证节点的信息都是正确的,如果某个节点出现故障,是如何发现的,

在etcdRegistry模块的run函数中,有一个ticker 10秒钟执行一次,这个ticker的作用就是没10秒从etcd读取到新的节点信息,保存到allServiceInfo的map中

func (er *EtcdRegistry) run() {
	ticker := time.NewTicker(MaxSyncServiceInterval)
	for {
		select {
		case service := <-er.serviceCh:

		case <-ticker.C:
			//同步AllServiceInfo
			er.syncServiceFromEtcd()

		default:
		
		}
	}
}

etcdRegistry模块中的syncServiceFromEtcd函数就是这个ticker需要执行函数:

首先申请一个新的allserviceInfoNew,用于存放service节点信息

从atomic.value中读取出allServiceInfo的信息,

遍历allServiceInfo的ServieMap,从里面去出Service.Name然后拼接成key,拼接出来的key是这样的

/ibinarytree/koala/comment_service/

如果出现错误 ,把老的map中的这个节点的信息,还保存成原样,存放到新的allServiceInfoNew中,否则

遍历从etcd服务器中读取的信息resp.Kvs,申请一个tmpService是吧从etcd中读取到的service信息放到tmpService临时变量中,然后再遍历tmpService.Nodes节点信息,放到ServiceNew中

然后把节点信息放到tmpService的Node切片中,再存放到allSercieInfoNew中,最后把allSercieInfoNew在存放到atomic.Value中

func (er *EtcdRegistry)syncServiceFromEtcd(){


	var allServiceInfoNew = &AllServiceInfo{
		serviceMap: make(map[string]*registry.Service, MaxServiceNum),
	}


	allServiceInfo := er.value.Load().(*AllServiceInfo)

	ctx := context.TODO()

	//对于缓存中的每一个服务都需要从etcd中更新
	for _, service :=range allServiceInfo.serviceMap{
		key := er.servicePath(service.Name)
		resp, err := er.client.Get(ctx, key, clientv3.WithPrefix())
		if err != nil {
			allServiceInfoNew.serviceMap[service.Name] = service
			continue
		}

		serviceNew := ®istry.Service{
			Name: service.Name,
		}

		for _, kv := range resp.Kvs {
			value := kv.Value
			var tmpService registry.Service
			tmpErr := json.Unmarshal(value, &tmpService)
			if tmpErr != nil {
				return
			}

			for _, node := range tmpService.Nodes {
				serviceNew.Nodes = append(serviceNew.Nodes, node)
			}
		}

		allServiceInfoNew.serviceMap[serviceNew.Name] = serviceNew
	}
	er.value.Store(allServiceInfoNew)
	fmt.Printf("background update all service success, len:%d\n",len(allServiceInfoNew.serviceMap))
}

 

你可能感兴趣的:(golang)