原文地址:gRPC proxy

gRPC代理是在gRPC层(L7)运行的无状态etcd反向代理。代理旨在减少核心etcd群集上的总处理负载。对于水平可伸缩性,它合并了监视和租约API请求。 为了保护集群免受滥用客户端的侵害,它会缓存关键范围请求。

gRPC代理支持多个etcd服务器端点。 代理启动时,它会随机选择一个etcd服务器端点来使用.该端点将处理所有请求,直到代理检测到端点故障为止。 如果gRPC代理检测到端点故障,它将切换到其他端点(如果有)以向其客户端隐藏故障。 将来可能会支持其他重试策略,例如加权轮询。

可扩展的监视 API


gRPC代理将同一键或范围上的多个客户端监视程序(c-watcher)合并为连接到etcd服务器的单个监视程序(s-watcher)。 代理将所有事件从S-watcher广播到其c-watcher。

假设N个客户端监视相同的密钥,则一个gRPC代理可以将etcd服务器上的监视负载从N减少到1。用户可以部署多个gRPC代理来进一步分配服务器负载。

在以下示例中,三个客户端监视键A。gRPC代理将三个监视程序合并,从而创建一个附加到etcd服务器的监视程序。

            +-------------+
| etcd 服务器 |
+------+------+
^ 监视 key A (s-watcher)
|
+-------+-----+
| gRPC 代理 | <-------+
| | |
++-----+------+ |监视 key A (c-watcher)
监视 key A ^ ^ 监视 key A |
(c-watcher) | | (c-watcher) |
+-------+-+ ++--------+ +----+----+
| 客户端 | | 客户端 | | 客户端 |
| | | | | |
+---------+ +---------+ +---------+

局限性

为了有效地将多个客户端监视程序合并为一个监视程序,gRPC代理在可能的情况下将新的c-watcher合并为现有的s-watcher。 由于网络延迟或缓冲的未传递事件,此合并的s-watcher可能与etcd服务器不同步。 如果未指定监视版本,则gRPC代理将不能保证c-watcher从最近的存储修订版本开始监视。 例如,如果客户端从具有修订版1000的etcd服务器监视,则该监视程序将从修订版1000开始。如果客户端从gRPC代理监视,则可以从修订版990开始监视。

类似的限制也适用于取消。 取消观察者后,etcd服务器的修订版可能大于取消响应修订版。

对于大多数用例,这两个限制不应引起问题。 将来,可能会有其他选项强制观察者绕过gRPC代理以获得更准确的修订响应。

可扩展的租约 API


为了保持其租约有效,客户端必须至少向一个etcd服务器建立一个gRPC流,以发送定期的心跳信号。 如果etcd工作负载涉及大量租约活动分布在许多客户端上,则这些流可能会导致CPU使用率过高。 为了减少核心群集上的流总数,该代理支持租约流合并。

假设N个客户端正在更新租约,则单个gRPC代理将etcd服务器上的流负载从N减少到1。部署中可能具有其他gRPC代理,以进一步在多个代理之间分配流。

在以下示例中,三个客户端更新了三个独立的租约(L1,L2和L3)。 gRPC代理将三个客户端租约流(c-stream)合并为连接到etcd服务器的单个租约保持活动流(s-stream)。 代理将客户端租用心跳从c流转发到s流,然后将响应返回到相应的c流。

          +-------------+
| etcd 服务器 |
+------+------+
^
| 心跳 L1, L2, L3
| (s-stream)
v
+-------+-----+
| gRPC 代理 +<-----------+
+---+------+--+ | 心跳 L3
^ ^ | (c-stream)
心跳 L1 | | 心跳 L2 |
(c-stream) v v (c-stream) v
+------+-+ +-+------+ +-----+--+
| 客户端 | | 客户端 | | 客户端 |
+--------+ +--------+ +--------+

客户保护滥用

gRPC代理在不违反一致性要求时会缓存请求的响应。 这可以保护etcd服务器免遭严密for循环中滥用客户端的侵害。

启动etcd gRPC代理


考虑一个etcd集群包括以下几个静态端点:

名字 地址 主机名
infra0 10.0.1.10 infra0.example.com
infra1 10.0.1.11 infra1.example.com
infra2 10.0.1.12 infra2.example.com

通过以下命令使用静态节点启动gRPC代理:

$ etcd grpc-proxy start --endpoints=infra0.example.com,infra1.example.com,infra2.example.com --listen-addr=127.0.0.1:2379

etcd gRPC启动并监听端口2379.它将客户端请求转发到上面提供的三个端点之一。

通过代理发送请求:

$ ETCDCTL_API=3 etcdctl --endpoints=127.0.0.1:2379 put foo bar
OK
$ ETCDCTL_API=3 etcdctl --endpoints=127.0.0.1:2379 get foo
foo
bar

客户端端点同步和名称解析


代理支持通过写入用户定义的端点来注册其端点以进行发现。 这有两个目的。 首先,它允许客户端将其端点与一组代理端点同步,以实现高可用性。 其次,它是etcd gRPC命名的端点提供程序。

通过提供用户定义的前缀来注册代理:

$ etcd grpc-proxy start --endpoints=localhost:2379 \
--listen-addr=127.0.0.1:23790 \
--advertise-client-url=127.0.0.1:23790 \
--resolver-prefix="___grpc_proxy_endpoint" \
--resolver-ttl=60 $ etcd grpc-proxy start --endpoints=localhost:2379 \
--listen-addr=127.0.0.1:23791 \
--advertise-client-url=127.0.0.1:23791 \
--resolver-prefix="___grpc_proxy_endpoint" \
--resolver-ttl=60

代理将会列出成员列表中的所有成员:

ETCDCTL_API=3 etcdctl --endpoints=http://localhost:23790 member list --write-out table

+----+---------+--------------------------------+------------+-----------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS |
+----+---------+--------------------------------+------------+-----------------+
| 0 | started | Gyu-Hos-MBP.sfo.coreos.systems | | 127.0.0.1:23791 |
| 0 | started | Gyu-Hos-MBP.sfo.coreos.systems | | 127.0.0.1:23790 |
+----+---------+--------------------------------+------------+-----------------+

这使客户端可以通过Sync自动发现代理端点:

cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{"http://localhost:23790"},
})
if err != nil {
log.Fatal(err)
}
defer cli.Close() // fetch registered grpc-proxy endpoints
if err := cli.Sync(context.Background()); err != nil {
log.Fatal(err)
}

注意,如果配置的代理没有解析程序前缀,

$ etcd grpc-proxy start --endpoints=localhost:2379 \
--listen-addr=127.0.0.1:23792 \
--advertise-client-url=127.0.0.1:23792

grpc-proxy的成员列表API返回其自己的advertise-client-url

ETCDCTL_API=3 etcdctl --endpoints=http://localhost:23792 member list --write-out table

+----+---------+--------------------------------+------------+-----------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS |
+----+---------+--------------------------------+------------+-----------------+
| 0 | started | Gyu-Hos-MBP.sfo.coreos.systems | | 127.0.0.1:23792 |
+----+---------+--------------------------------+------------+-----------------+

命名空间


假设一个应用程序期望对整个键空间有完全控制,但是etcd集群与其他应用程序共享。 为了使所有应用程序都不会相互干扰地运行,代理可以对etcd键空间进行分区,以便客户端可以访问完整的键空间。 当给代理提供标志--namespace时,所有进入代理的客户端请求都将转换为在键上具有用户定义的前缀。 对etcd集群的访问将在前缀下,而来自代理的响应将删除该前缀;对于客户端,显然根本没有前缀。

要为代理命名空间,请通过--namespace启动:

$ etcd grpc-proxy start --endpoints=localhost:2379 \
--listen-addr=127.0.0.1:23790 \
--namespace=my-prefix/

现在,对代理的访问在etcd集群上透明地加上前缀:

$ ETCDCTL_API=3 etcdctl --endpoints=localhost:23790 put my-key abc
# OK
$ ETCDCTL_API=3 etcdctl --endpoints=localhost:23790 get my-key
# my-key
# abc
$ ETCDCTL_API=3 etcdctl --endpoints=localhost:2379 get my-prefix/my-key
# my-prefix/my-key
# abc

TLS终端


使用来自安全etcd群集的TLS的gRPC代理终端为未加密的本地端点提供服务.

使用客户端https启动单个成员etcd集群尝试:

$ etcd --listen-client-urls https://localhost:2379 --advertise-client-urls https://localhost:2379 --cert-file=peer.crt --key-file=peer.key --trusted-ca-file=ca.crt --client-cert-auth

确认客户端端口正在提供https:

# fails
$ ETCDCTL_API=3 etcdctl --endpoints=http://localhost:2379 endpoint status
# works
$ ETCDCTL_API=3 etcdctl --endpoints=https://localhost:2379 --cert=client.crt --key=client.key --cacert=ca.crt endpoint status

接下来,通过使用客户端证书连接到etcd端点https://localhost2379localhost:12379上启动gRPC代理:

$ etcd grpc-proxy start --endpoints=https://localhost:2379 --listen-addr localhost:12379 --cert client.crt --key client.key --cacert=ca.crt --insecure-skip-tls-verify &

最后,通过在http上将密钥放入代理来测试TLS终端:

$ ETCDCTL_API=3 etcdctl --endpoints=http://localhost:12379 put abc def
# OK

指标和健康


gRPC代理为--endpoints定义的etcd成员公开了/health和Prometheus/metrics端点。 另一种方法是定义一个附加URL,该URL将使用--metrics-addr参数来响应/metrics/health端点。

$ etcd grpc-proxy start \
--endpoints https://localhost:2379 \
--metrics-addr https://0.0.0.0:4443 \
--listen-addr 127.0.0.1:23790 \
--key client.key \
--key-file proxy-server.key \
--cert client.crt \
--cert-file proxy-server.crt \
--cacert ca.pem \
--trusted-ca-file proxy-ca.pem

已知问题

代理的主接口同时服务于HTTP2和HTTP/1.1。如果如上例所示,使用TLS设置了代理,则在监听接口上使用诸如cURL之类的客户端时,将要求在返回/metrics/health的请求上将协议显式设置为HTTP/1.1。通过使用--metrics-addr参数,辅助接口将没有此要求。

 $ curl --cacert proxy-ca.pem --key proxy-client.key --cert proxy-client.crt https://127.0.0.1:23790/metrics --http1.1

ETCD:gRPC代理的更多相关文章

  1. ETCD:gRPC命名与发现

    原文地址:gRPC naming and discovery etcd提供一个gRPC解析器支持备用的命名系统,该命名系统从etcd获取主机以发现gRPC服务.以下机制基于监视对以服务名称为前缀的Ke ...

  2. etcd代理组件的开发思想

    最近在一个项目中,需要使用到etcd集群来实现服务发现的功能,目的是统一管理相应的服务资源,同时也可对资源做一定的负载均衡策略.然而,项目中使用的技术栈是C++语言,github上没有合适的C++开源 ...

  3. 什么是Etcd?

    文章大部分引至:http://jolestar.com/etcd-architecture/ Etcd 按照官方介绍 Etcd is a distributed, consistent key-val ...

  4. ETCD:配置参数

    原文地址:Configuration flags etcd通过配置文件,多命令行参数和环境变量进行配置, 可重用的配置文件是YAML文件,其名称和值由一个或多个下面描述的命令行标志组成.为了使用此文件 ...

  5. ETCD:文档

    原文地址:Documentation 文档 etcd是一个分布式键值对存储,被设计为可靠的,快速的保存并提供对关键数据的访问.通过分布式锁,领导选举和写屏障使能分布式一致性.一个etcd集群旨在实现高 ...

  6. 什么是Etcd,如何运维Etcd ?

    介绍 ETCD 是一个分布式.可靠的 key-value 存储的分布式系统,用于存储分布式系统中的关键数据:当然,它不仅仅用于存储,还提供配置共享及服务发现:基于Go语言实现. ETCD的特点 简单: ...

  7. 基于知名微服务框架go-micro开发gRPC应用程序

    go-micro是golang的一个微服务框架. go-micro各个版本之间的兼容性问题一直被诟病,前几年go-micro更是分化出了两个分支: 一个延续了go-micro,只不过转到了其公司CEO ...

  8. 转:etcd:从应用场景到实现原理的全方位解读

    原文来自于:http://www.infoq.com/cn/articles/etcd-interpretation-application-scenario-implement-principle ...

  9. 分布式键值存储系统ETCD调研

    分布式键值存储系统ETCD调研 简介 etcd是一个开源的分布式键值存储工具--为CoreOS集群提供配置服务.发现服务和协同调度.Etcd运行在集群的每个coreos节点上,可以保证coreos集群 ...

随机推荐

  1. 如果你不了解Java的JVM,那真的很难进BAT一线大厂!

    前言 对于开发人员来说,如果不了解Java的JVM,那真的是很难写得一手好代码,很难查得一手好bug.同时,JVM也是面试环节的中重灾区.我们不能为了面试而面试,但是学习会这些核心知识你必定会成为面试 ...

  2. 浅析堆栈段,BBS段,数据段,代码段

    文章目录 1. 进程,线程 2. 堆栈段 3. BBS段 4. 代码段 5. 数据段 6. 例子 7. 总结 1. 进程,线程 所谓进程是指在系统中能独立运行并作为资源分配的基本单位,程序段,数据段和 ...

  3. 使用t-SNE做降维可视化

    最近在做一个深度学习分类项目,想看看训练集数据的分布情况,但由于数据本身维度接近100,不能直观的可视化展示,所以就对降维可视化做了一些粗略的了解以便能在低维空间中近似展示高维数据的分布情况,以下内容 ...

  4. C#总结(七)动态加载C++动态链接库

    C#调用C++ 链接库的方式分为静态调用和动态调用这两种方式.静态调用之前的文章里面都有介绍,使用.net 提供的DllImport 导入相关的C++ 库即可.请看之前的文章,https://www. ...

  5. ArcGIS JS 4加载第三方矢量切片

        现在矢量切片越来越普及,对于地图渲染能更轻更快.ArcGIS JS 4.13可以实现加载第三方矢量切片,以下为代码示例,最下方是我之前切的建筑物数据.     当切片大小在1M左右,加载效果还 ...

  6. 我也开源... React Native Messager

    近期有空,玩转React Native. https://github.com/andyc365/ReactNativeMessager React Native Messager A React N ...

  7. 敏捷:你能区分DevOps中的“集成、部署、交付、上线、发布”吗?

    在DevOps中,你可能经常会听到类似这样的一些话: 功能还没集成进来. 功能还没部署上去. 功能还没交付. 功能还没上线. 功能还没发布. 请问,以上“集成”.“部署”. “交付”.“上线”.“发布 ...

  8. day03运算符、表达式、自增自减、三目运算符、程序结构、用户输入

    复习 1.java的输出语句 1)System.out.println(); 2)System.out.print(); 2.注释 1)单行注释 // 2)多行注释 /* .... */ 3.变量 1 ...

  9. zip,rar及linux下常用的压缩格式

    日常操作中我们经常使用到文件压缩操作,其使用一些特定的算法来减小文件的大小,可以提高传输数据时的速率和减少数据在一些存储机制上占有的空间大小,实现空间利用最大化. 比如:如果你想通过邮箱发送一个文件夹 ...

  10. LINUX OS 正常关机失败

    描述:LINUX OS运行命令shutdown now显示:Telling INIT to go to single user mode....   解决方法:运行命令exit重新登录,再运行 hal ...