etcd学习和实战:2、本地集群测试及gRPC命名和发现

etcd学习和实战:2、本地集群测试及gRPC命名和发现


文章目录

1. 前言

前面我们已经简单了解并安装了etcd,由于etcd的应用场景较多,我这里只针对我目前使用的场景进行深入学习和总结,我们的使用场景之前已经说过了,主要是使用etcd的服务注册发现功能,这里我们先利用官网的开发者指南搭建本地集群用于后续测试,然后看下如何将gRPC和etcd结合用于发现gRPC服务。

2. 搭建集群

这里主要是根据:https://etcd.io/docs/v3.4/dev-guide/local_cluster/的内容,所以如果版本不同或者存在一些问题的话,可以去官网的开发者文档中找关于本地集群相关的内容或者issue相关内容进行参考解决。

2.1 本地独立集群

这个就是上节我们安装的单个etcd程序,启动集群则直接运行编译安装后的程序即可:

/tmp/test-etcd/etcd

etcd学习和实战:2、本地集群测试及gRPC命名和发现

正在运行的 etcd 成员侦听localhost:2379客户端请求。

之后我们在不写客户端程序的情况下可以直接使用etcdctl这个命令行程序作为客户端进行简单的key-value读写确认集群正常工作:

etcd学习和实战:2、本地集群测试及gRPC命名和发现

2.2 本地多成员集群

  • 安装goreman

Procfile在ETCD git仓库的基座被设置成很容易地配置一个本地多构件集群。要启动多成员集群,请导航到 etcd 源代码树的根目录并执行以下操作:

cd $HOME/etcd
go get github.com/mattn/goreman
  • 设置环境变量

设置环境变量,把$GOPATH/bin也加入环境变量,由go get安装的包的可执行程序默认会放在对应目录下,所以我们安装的goreman不添加路径执行的话需要设置这一步,一般来说当我们通过go mod管理go相关包时需要设置该环境变量:

echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.bashrc
source ~/.bashrc
  • 利用goreman使用etcd的Procfile启动集群
goreman -f Procfile start

etcd学习和实战:2、本地集群测试及gRPC命名和发现

3. 与集群交互

3.1 打印成员列表

etcdctl --write-out=table --endpoints=localhost:2379 member list

etcd学习和实战:2、本地集群测试及gRPC命名和发现

3.2 存储示例键值对

在集群中存储一个键值对:

$ etcdctl put foo bar
OK

如果打印OK,则表示键值对存储成功。

4. 测试容错

要行使 etcd 的容错能力,请杀死一个成员并尝试检索key。

  1. 标识要停止的成员的进程名称。

    Procfile列出了多构件簇的性质。例如,考虑进程名称为 的成员etcd2

  2. 停止成员:

    # kill etcd2
    $ goreman run stop etcd2
    
  3. 存储key:

    $ etcdctl put key hello
    OK
    
  4. 检索上一步中存储的key:

    $ etcdctl get key
    hello
    
  5. 从停止的成员中检索key:

    $etcdctl --endpoints=localhost:22379 get key
    

    该命令应显示由连接失败引起的错误:

     {"level":"warn","ts":"2021-06-02T17:34:17.210+0800","caller":"clientv3/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"endpoint://client-9a0c0666-5e94-403d-b31e-0396b627387e/localhost:22379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = latest balancer error: all SubConns are in TransientFailure, latest connection error: connection error: desc = \"transport: Error while dialing dial tcp 127.0.0.1:22379: connect: connection refused\""}
     Error: context deadline exceeded
    
  6. 重启停止的成员:

    $goreman run restart etcd2
    
  7. 从重新启动的成员获取密钥:

    $ etcdctl --endpoints=localhost:22379 get key
    hello
    

    重新启动成员重新建立连接。etcdctl现在将能够成功检索密钥。要了解有关与 etcd 交互的更多信息,请阅读与 etcd 交互部分

5. gRPC命名和发现

go-grpc:用于使用 etcd 后端解析 gRPC 端点

etcd 提供了一个 gRPC 解析器来支持替代名称系统,该系统从 etcd 获取端点以发现 gRPC 服务。底层机制基于监视以服务名称为前缀的键的更新。

5.1 在go-grpc中使用etcd发现

etcd 客户端提供了一个 gRPC 解析器,用于使用 etcd 后端解析 gRPC 端点。解析器使用 etcd 客户端初始化,并给出解析目标:

import (
   "go.etcd.io/etcd/clientv3"
   etcdnaming "go.etcd.io/etcd/clientv3/naming"

   "google.golang.org/grpc"
)

...

cli, cerr := clientv3.NewFromURL("http://localhost:2379")
r := &etcdnaming.GRPCResolver{Client: cli}
b := grpc.RoundRobin(r)
conn, gerr := grpc.Dial("my-service", grpc.WithBalancer(b), grpc.WithBlock(), ...)

5.2 管理服务端点

etcd 解析器将解析目标前缀下的所有key(例如,“my-service/”)和 JSON 编码的 go-grpcnaming.Update值视为潜在的服务端点。端点通过创建新的键并通过删除键从服务中删除。

5.2.1 添加端点

可以通过以下方式将新端点添加到服务中etcdctl

ETCDCTL_API=3 etcdctl put my-service/1.2.3.4 '{"Addr":"1.2.3.4","Metadata":"..."}'

etcd 客户端的GRPCResolver.Update方法还可以使用匹配的key注册新端点Addr

r.Update(context.TODO(), "my-service", naming.Update{Op: naming.Add, Addr: "1.2.3.4", Metadata: "..."})

5.2.2 删除端点

可以通过以下方式从服务中删除主机etcdctl

ETCDCTL_API=3 etcdctl del my-service/1.2.3.4

etcd 客户端的GRPCResolver.Update方法也支持删除端点:

r.Update(context.TODO(), "my-service", naming.Update{Op: naming.Delete, Addr: "1.2.3.4"})

5.2.3 使用租约注册端点

使用租约注册端点可确保如果主机无法维持保持活动的心跳(例如,其机器出现故障),它将从服务中删除:

lease=`ETCDCTL_API=3 etcdctl lease grant 5 | cut -f2 -d' '`
ETCDCTL_API=3 etcdctl put --lease=$lease my-service/1.2.3.4 '{"Addr":"1.2.3.4","Metadata":"..."}'
ETCDCTL_API=3 etcdctl lease keep-alive $lease

6. 最后

到这里我们应该已经知道如何利用etcd来处理gRPC服务的发现和管理了,接下来我们将分别用Java和go写一些测试的gRPC服务然后和我们搭建的etcd集群结合起来进行测试。

上一篇:(二)grpc-protobuf 数据类型


下一篇:grpc(五)