Golang分布式应用之etcd

etcd是一个可靠的分布式KV存储数据库,由CoreOS开源。Kuberentes使用etcd作为其存储引擎,随着云原生的火热,etcd也逐渐广泛应用起来。

etcd除了作为普通的KV存储、配置存储,还可以用在以下分布式场景中:

  • 服务发现
  • 分布式锁
  • 选主
  • 分布式队列
  • 分布式系统协调

本文结合Golang来编写对应的中间件,所有代码见 github.com/qingwave/go…

服务发现

在分布式系统中,如何能找到所需要访问的服务即服务发现。服务较少时可以直接访问其IP,但随着业务规模的扩大,维护其地址越来越复杂,如果服务频繁的扩缩容,必须能够实时感应服务的断点变化。 通常有多种方式可以解决

  1. 系统级别,如LVS、DNS、Kubernetes中的Service、Istio等
  2. 微服务注册中心,如Spring Cloud中的Enruka,Dubbo等
  3. 借助分布式协调系统etcd、ZK、Consul等

服务发现提供的功能包括:

  • 服务注册、注销
  • 服务宕机或异常时,自动注销
  • 感知服务端点变化

借助etcd实现服务发现

  • 可以通过将端点写同一个目录(相同前缀,如/services/job/endpoint1, /services/job/endpoint2),并通过Lease设置一个过期时间,不断刷新Lease,如果服务宕机,Lease过期对应端点会自动删除
  • 通过Watch API可以监听端点变化

主要代码如下

func New(config EtcdDiscoveryConfig) (*EtcdDiscovery, error) {
    // 创建session,session会自动续约
	session, err := concurrency.NewSession(config.Client, concurrency.WithTTL(config.TTLSeconds))
	if err != nil {
		return nil, err
	}
	config.Prefix = strings.TrimSuffix(config.Prefix, "/") + "/"
	return &EtcdDiscovery{
		EtcdDiscoveryConfig: config,
		session:             session,
		myKey:               config.Prefix + config.Key,
		services:            make(map[string]string),
	}, nil
}

func (d *EtcdDiscovery) Register(ctx context.Context) error {
	lease := d.session.Lease()
    // 注册服务
	_, err := d.Client.Put(ctx, d.myKey, d.Val, clientv3.WithLease(lease))
	return err
}

func (d *EtcdDiscovery) UnRegister(ctx context.Context) error {
    // 注销服务
	_, err := d.Client.Delete(ctx, d.myKey)
	return err
}

// 监听端点变化
func (d *EtcdDiscovery) Watch(ctx context.Context) error {
    // context用来停止监听
	d.watchContext, d.watchCancel = context.WithCancel(ctx)
    // 首先获取所有端点
	resp, err := d.Client.Get(d.watchContext, d.Prefix, clientv3.WithPrefix())

	services := make(map[string]string)
	for _, kv := range resp.Kvs {
		services[string(kv.Key)] = string(kv.Value)
	}
	d.setServices(services)

    // 回调点,用户可自定义
	if d.Callbacks.OnStartedDiscovering != nil {
		d.Callbacks.OnStartedDiscovering(d.ListServices())
	}

	defer func() {
		if d.Callbacks.OnStoppedDiscovering != nil {
			d.Callbacks.OnStoppedDiscovering()
		}
	}()

	defer d.watchCancel()
    // 监听目录,通过WithPrefix可以添加子目录变化
	ch := d.Client.Watch(d.watchContext, d.Prefix, clientv3.WithPrefix())
	for {
		select {
		case <-d.watchContext.Done():
			return nil
		case wr, ok := <-ch:
			if !ok {
				return fmt.Errorf("watch closed")
			}
			if wr.Err() != nil {
				return wr.Err()
			}
            // 将添加事件同步到本地端点列表
			for _, ev := range wr.Events {
				key, val := string(ev.Kv.Key), string(ev.Kv.Value)
				switch ev.Type {
				case mvccpb.PUT:
					d.addService(key, val)
				case mvc
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Golang分布式任务框架是使用Golang编程语言开发的一种工具,用于简化分布式环境下的任务调度和处理。 首先,Golang分布式任务框架提供了一个简单而强大的任务调度器,可以将任务分配给不同的节点进行并行处理。这个调度器可以根据任务的类型和优先级来动态地分配任务,并且可以实时监控任务的执行情况和进度。 其次,该框架提供了一套灵活的任务管理机制,可以方便地定义和管理任务。我们可以通过编写简单的代码来定义任务的逻辑,并且可以为任务设置各种参数,例如执行时间间隔、重试次数等。此外,该框架还支持任务的持久化存储,确保任务在节点故障或系统重启后能够正确地恢复和继续执行。 此外,Golang分布式任务框架还提供了一套高效的通信机制,用于节点之间的消息传递和数据交换。通过这种通信机制,不同节点之间可以共享任务和数据,实现更加高效和协同的任务处理。此外,该框架还支持集群的动态扩展和节点的负载均衡,以应对不同规模和负载的分布式环境。 总结来说,Golang分布式任务框架通过提供强大的任务调度、任务管理和通信机制,简化了分布式环境下的任务处理。它具有灵活、高效和可靠的特点,适用于各种规模和负载的分布式系统应用。通过使用该框架,我们可以更加轻松地开发和管理分布式任务,提高系统的性能和可扩展性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值