//sevice.go

package discoveryimport ("context""errors""sync""time""github.com/coreos/etcd/clientv3"l4g "github.com/alecthomas/log4go"
)type Service struct {closeChan chan struct{}    //关闭通道client    *clientv3.Client //etcd v3 clientleaseID   clientv3.LeaseID //etcd 租约idkey       string           //键val       string           //值
    wg        sync.WaitGroup
}// NewService 构造一个注册服务
func NewService(etcdEndpoints []string, key string, val string) (*Service, error) {cli, err := clientv3.New(clientv3.Config{Endpoints:   etcdEndpoints,DialTimeout: 2 * time.Second,})if nil != err {return nil, err}s := &Service{client:    cli,closeChan: make(chan struct{}),key:       key,val:       val,}return s, nil
}// Start 开启注册
// @param - ttlSecond 租期(秒)
func (s *Service) Start(ttlSecond int64) error {// minimum lease TTL is 5-secondresp, err := s.client.Grant(context.TODO(), ttlSecond)if err != nil {panic(err)}s.leaseID = resp.ID_, err = s.client.Put(context.TODO(), s.key, s.val, clientv3.WithLease(s.leaseID))if err != nil {panic(err)}ch, err1 := s.client.KeepAlive(context.TODO(), s.leaseID)if nil != err1 {panic(err)}l4g.Info("[discovery] Service Start leaseID:[%d] key:[%s], value:[%s]", s.leaseID, s.key, s.val)s.wg.Add(1)defer s.wg.Done()for {select {case <-s.closeChan:return s.revoke()case <-s.client.Ctx().Done():return errors.New("server closed")case ka, ok := <-ch:if !ok {l4g.Warn("[discovery] Service Start keep alive channel closed")return s.revoke()} else {l4g.Fine("[discovery] Service Start recv reply from Service: %s, ttl:%d", s.key, ka.TTL)}}}return nil
}// Stop 停止
func (s *Service) Stop() {close(s.closeChan)s.wg.Wait()s.client.Close()
}func (s *Service) revoke() error {_, err := s.client.Revoke(context.TODO(), s.leaseID)if err != nil {l4g.Error("[discovery] Service revoke key:[%s] error:[%s]", s.key, err.Error())} else {l4g.Info("[discovery] Service revoke successfully key:[%s]", s.key)}return err
}

//watch.go

package discoveryimport ("context""os""time""github.com/coreos/etcd/clientv3""github.com/coreos/etcd/mvcc/mvccpb"l4g "github.com/alecthomas/log4go""google.golang.org/grpc/grpclog")type GroupManager struct {wg     sync.WaitGroupctx    context.Contextcancel context.CancelFunconce   sync.Once
}func NewGroupManager() *GroupManager {ret := new(GroupManager)ret.ctx, ret.cancel = context.WithCancel(context.Background())return ret
}func (this *GroupManager) Close() {this.once.Do(this.cancel)
}func (this *GroupManager) Wait() {this.wg.Wait()
}func (this *GroupManager) Add(delta int) {this.wg.Add(delta)
}func (this *GroupManager) Done() {this.wg.Done()
}func (this *GroupManager) Chan() <-chan struct{} {return this.ctx.Done()
}type Target interface {Set(string, string)Create(string, string)Modify(string, string)Delete(string)
}type Config struct {Servers        []stringDailTimeout    int64RequestTimeout int64Prefix         boolTarget         string
}func Watch(gm *GroupManager, cfg *Config, target Target) {defer gm.Done()cli, err := clientv3.New(clientv3.Config{Endpoints:   cfg.Servers,DialTimeout: time.Duration(cfg.DailTimeout) * time.Second,})if err != nil {panic(err.Error())return}defer cli.Close() // make sure to close the client
l4g.Info("[discovery] start watch %s", cfg.Target)ctx, cancel := context.WithTimeout(context.Background(), time.Duration(cfg.RequestTimeout)*time.Second)var resp *clientv3.GetResponseif cfg.Prefix {resp, err = cli.Get(ctx, cfg.Target, clientv3.WithPrefix())} else {resp, err = cli.Get(ctx, cfg.Target)}cancel()if err != nil {panic(err.Error())}for _, ev := range resp.Kvs {target.Set(string(string(ev.Key)), string(ev.Value))}var rch clientv3.WatchChanif cfg.Prefix {rch = cli.Watch(context.Background(), cfg.Target, clientv3.WithPrefix(), clientv3.WithRev(resp.Header.Revision+1))} else {rch = cli.Watch(context.Background(), cfg.Target, clientv3.WithRev(resp.Header.Revision+1))}for {select {case <-gm.Chan():l4g.Info("[discovery] watch %s close", cfg.Target)returncase wresp := <-rch:err := wresp.Err()if err != nil {l4g.Info("[discovery] watch %s response error: %s ", cfg.Target, err.Error())gm.Close()return}l4g.Debug("[discovery] watch %s response %+v", cfg.Target, wresp)for _, ev := range wresp.Events {if ev.IsCreate() {target.Create(string(ev.Kv.Key), string(ev.Kv.Value))} else if ev.IsModify() {target.Modify(string(ev.Kv.Key), string(ev.Kv.Value))} else if ev.Type == mvccpb.DELETE {target.Delete(string(ev.Kv.Key))} else {l4g.Error("[discovery] no found watch type: %s %q", ev.Type, ev.Kv.Key)}}}}
}

转载于:https://www.cnblogs.com/mrblue/p/9722682.html

Golang etcd服务注册与发现相关推荐

  1. go语言高并发与微服务实战_go-micro+gin+etcd微服务实战之服务注册与发现

    在构建微服务时,使用服务发现可以减少配置的复杂性,本文以go-micro为微服务框架,使用etcd作为服务发现服务,使用gin开发golang服务. 使用gin 的原因是gin能够很好的和go-mic ...

  2. etcd 访问 锁_在系统中用etcd实现服务注册和发现

    系统中实现服务注册与发现所需的基本功能有 服务注册:同一service的所有节点注册到相同目录下,节点启动后将自己的信息注册到所属服务的目录中. 健康检查:服务节点定时发送心跳,注册到服务目录中的信息 ...

  3. 在系统中用etcd实现服务注册和发现

    系统中实现服务注册与发现所需的基本功能有 服务注册:同一service的所有节点注册到相同目录下,节点启动后将自己的信息注册到所属服务的目录中. 健康检查:服务节点定时发送心跳,注册到服务目录中的信息 ...

  4. 用etcd实现服务注册和发现

    系统中实现服务注册与发现所需的基本功能有 服务注册:同一service的所有节点注册到相同目录下,节点启动后将自己的信息注册到所属服务的目录中. 健康检查:服务节点定时发送心跳,注册到服务目录中的信息 ...

  5. ETCD 十六 服务注册与发现

    微服务架构中的服务注册与发现 在微服务架构中,多个微服务间的通信需要依赖服务注册与发现组件获取指定服务实例的地址信息,才能正确地发起 RPC 调用,保证分布式系统的高可用.高并发.服务注册与发现主要包 ...

  6. 微服务框架 Go-Micro 集成 Nacos 实战之服务注册与发现

    作者 | 张斌斌 导读:本文主要介绍如何使用 Golang 生态中的微服务框架 Go-Micro(v2) 集成 Nacos 进行服务注册与发现.(Go-Micro 目前已经是 v3 版本,但由于某些原 ...

  7. 微服务框架Go-Micro集成Nacos实战之服务注册与发现

    简介:本文主要介绍如何使用 Golang 生态中的微服务框架 Go-Micro(v2) 集成 Nacos 进行服务注册与发现.(Go-Micro 目前已经是 v3 版本,但由于某些原因项目已经更名为 ...

  8. 【华为云专家原创】 服务注册与发现如何满足服务治理?

    摘要:本文主要介绍了服务注册与发现的原理,以及常用的几种服务注册与发现组件介绍对比. 在单体应用向微服务架构演进的过程中,原本的巨石型应用会按照业务需求被拆分成多个微服务,每个服务提供特定的功能,并可 ...

  9. 一个故事,一段代码告诉你如何使用不同语言(GolangC#)提供相同的能力基于Consul做服务注册与发现

    文章目录 引言 什么是微服务 传统服务 微服务 什么是服务注册与服务发现 为什么要使用不同的语言提供相同的服务能力 服务协调器 服务注册 Golang C#(.NetCore3.1) 服务发现 通过H ...

最新文章

  1. 23 种设计模式的通俗解释
  2. Win7环境下VS2010配置Cocos2d-x-2.1.4最新版本的开发环境(亲测)
  3. [2018/11/14]关于学习的思考
  4. Java中的状态设计模式–示例教程
  5. python为什么这么小_同样是 Python,怎么区别这么大
  6. Falsy Bouncer-freecodecamp算法题目
  7. flutter用英语怎么说_碍手碍脚用英语怎么说?
  8. ftp 相关知识集合
  9. windows2003 IIS6 部署MVC4程序等等
  10. mvc npoi将List实体导出excel的最简单方法
  11. Ubuntu安装和显卡驱动安装
  12. 以WBS模板和PBS自动生成WBS计划任务
  13. ImageJ java 调用_用ImageJ快速分析和处理图像
  14. 矩形口径喇叭天线设计——参数设置
  15. 【idea基础知识】idea在merge时颜色不同的各个区块代表的意思
  16. ubntu 五笔输入法 打不出词组
  17. 基于SSH的校园网上订餐系统
  18. 【Pytorch神经网络理论篇】 34 样本均衡+分类模型常见损失函数
  19. AndroidStudio蓝牙通信
  20. 谷歌安装插件Fatkun 批量保存网页图片

热门文章

  1. 机器学习实战案例:使用随机森林/XGBoost等模型进行分类预测,提高银行营销活动效率
  2. 集成学习(Bagging、Boosting、Stacking)算法原理与算法步骤
  3. phpmailer 私密抄送_最详细的phpmailer的使用方法
  4. android 判断华为系统版本号,Android获取系统(ROM)类别及版本号
  5. cocoscreator webview 视频直播
  6. 知乎 鸿蒙目前只是安卓移植,[转载]转载:华为鸿蒙,一个本属于2025年的产品...
  7. unity edit模式下停止运行
  8. python 通过电话号码获取微信性别信息
  9. Dijkstra算法图文详解
  10. 如何使用MFC编写自定义UI界面【附高仿QQ 2014登陆界面范例程序】