对于搞微服务的同学来说,服务注册、服务发现的概念应该不会太陌生。
简单来说,当服务A需要依赖服务B时,我们就需要告诉服务A,哪里可以调用到服务B,这就是服务注册发现要解决的问题。
Service B
把自己注册到 Service Registry
叫做 服务注册
Service A
从 Service Registry
发现 Service B
的节点信息叫做 服务发现
服务注册是针对服务端的,服务启动后需要注册,分为几个部分:
启动注册
定时续期
退出撤销
当一个服务节点起来之后,需要把自己注册到 Service Registry
上,便于其它节点来发现自己。注册需要在服务启动完成并可以接受请求时才会去注册自己,并且会设置有效期,防止进程异常退出后依然被访问。
定时续期相当于 keep alive
,定期告诉 Service Registry
自己还在,能够继续服务。
当进程退出时,我们应该主动去撤销注册信息,便于调用方及时将请求分发到别的节点。同时,go-zero 通过自适应的负载均衡来保证即使节点退出没有主动注销,也能及时摘除该节点。
服务发现是针对调用端的,一般分为两类问题:
存量获取
增量侦听
还有一个常见的工程问题是
应对服务发现故障
当服务发现服务(比如 etcd, consul, nacos等)出现问题的时候,我们不要去修改已经获取到的 endpoints 列表,从而可以更好的确保 etcd 等宕机后所依赖的服务依然可以正常交互。
当 Service A
启动时,需要从 Service Registry
获取 Service B
的已有节点列表:Service B1
, Service B2
, Service B3
,然后根据自己的负载均衡算法来选择合适的节点发送请求。
上图已经有了 Service B1
, Service B2
, Service B3
,如果此时又启动了 Service B4
,那么我们就需要通知 Service A
有个新增的节点。如图:
对于服务调用方来说,我们都会在内存里缓存一个可用节点列表。不管是使用 etcd
,consul
或者 nacos
等,我们都可能面临服务发现集群故障,以 etcd
为例,当遇到 etcd
故障时,我们就需要冻结 Service B
的节点信息而不去变更,此时一定不能去清空节点信息,一旦清空就无法获取了,而此时 Service B
的节点很可能都是正常的,并且 go-zero
会自动隔离和恢复故障节点。
服务注册、服务发现的基本原理大致如此,当然实现起来还是比较复杂的,接下来我们一起看看 go-zero
里支持哪些服务发现的方式。
go-zero
默认支持三种服务发现方式:
直连
基于 etcd 的服务发现
基于 kubernetes endpoints 的服务发现
直连是最简单的方式,当我们的服务足够简单时,比如单机即可承载我们的业务,我们可以直接只用这种方式。
在 rpc
的配置文件里直接指定 endpoints
即可,比如:
Rpc: Endpoints: - 192.168.0.111:3456 - 192.168.0.112:3456
zrpc
调用端就会分配负载到这两个节点上,其中一个节点有问题时 zrpc
会自动摘除,等节点恢复时会再次分配负载。
这个方法的缺点是不能动态增加节点,每次新增节点都需要修改调用方配置并重启。
当我们的服务有一定规模之后,因为一个服务可能会被很多个服务依赖,我们就需要能够动态增减节点,而无需修改很多的调用方配置并重启。
常见的服务发现方案有 etcd
, consul
, nacos
等。
go-zero内置集成了基于 etcd
的服务发现方案,具体使用方法如下:
Rpc: Etcd: Hosts: - 192.168.0.111:2379 - 192.168.0.112:2379 - 192.168.0.113:2379 Key: user.rpc
Hosts
是 etcd
集群地址
Key
是服务注册上去的 key
如果我们的服务都是部署在 Kubernetes
集群上的话,Kubernetes
本身是通过自带的 etcd
管理集群状态的,所有的服务都会把自己的节点信息注册到 Endpoints
对象,我们可以直接给 deployment
权限去读取集群的 Endpoints
对象即可获得节点信息。
Service B
的每个 Pod
启动时,会将自己注册到集群的 Endpoints
里
Service A
的每个 Pod
启动时,可以从集群的 Endpoints
里获取 Service B
的节点信息
当 Service B
的节点发生改变时,Service A
可以通过 watch
集群的 Endpoints
感知到
在这个机制工作之前,我们需要配置好当前 namespace
内 pod
对集群 Endpoints
访问权限,这里有三个概念:
ClusterRole
定义集群范围的权限角色,不受 namespace
控制
ServiceAccount
定义 namespace
范围内的 service account
ClusterRoleBinding
将定义好的 ClusterRole
和不同 namespace
的 ServiceAccount
进行绑定
具体的 Kubernetes
配置文件可以参考 这里,其中 namespace
按需修改。
注意:当启动时报没有权限获取 Endpoints
时记得检查这些配置有没落实 :)
zrpc
的基于 Kubernetes Endpoints
的服务发现使用方法如下:
Rpc: Target: k8s://mynamespace/myservice:3456
其中:
mynamespace
:被调用的 rpc
服务所在的 namespace
myservice
:被调用的 rpc
服务的名字
3456:被调用的 rpc
服务的端口
在创建 deployment
配置文件时一定要加上 serviceAccountName
来指定使用哪个 ServiceAccount
,示例如下:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: alpine spec: replicas: 1 selector: matchLabels: app: alpine template: metadata: labels: app: alpine spec: serviceAccountName: endpoints-reader containers: - name: alpine image: alpine command: - sleep - infinity
注意其中第17行指定 serviceAccountName
,指定该 deployment
创建出来的 pod
用什么 ServiceAccount
。
v2ray服务(WebSocket+TLS+Web)在PC端客户端可以连上正常使用,但iOS手机端用shadowrocket客户端能连上,但无法上网。报错信息如下:v2ray.com/core/proxy/vmess/encoding: invalid user > v2ray.com/core/proxy/vmess: Not Found
社工库免费查询,免费社工库电报(Telegram)机器人。
YouTube俗称“油管”,它是全球规模最大的视频网站。很多人知道如何如何上传Youtube视频,但却不知道如何下载Youtube视频。本文将手把手教你如何下载Youtube影片,并为大家推荐3个最佳的Youtube下载方法和8个最佳的Youtube下载工具。
什么是服务注册发现?简单来说,当服务A需要依赖服务B时,我们就需要告诉服务A,哪里可以调用到服务B,这就是服务注册发现要解决的问题。
本文介绍了分布式事务的一些基础理论,并对常用的分布式事务方案进行了讲解;在文章的后半部分还给出了事务异常的原因、分类以及优雅的解决方案;最后以一个可运行的分布式事务例子,将前面介绍的内容以简短的程序进行演示。
MySQL主从复制异常,binlog文件丢失,但relay log日志完整,重新启动复制,是否会正常运行,数据完整性和一致性能否保证呢?
Polygon
过去 3 个月,整个 web3 生态的每周活跃开发者才不到 5k(GitHub 数据统计,实际上会更多一些)。如何早期进入这个领域并成为 top 10% 的开发者,下面的几门课可以帮助你打下一个坚实的基础。
2020 年初,Ethereum的费用对大多数 DeFi 用户还是友好的。但随着Ethereum生态在DeFi Summer的迅速发展,TVL和新用户迅速增长的同时也导致了合约交互的Gas费水涨船高,让资金量较少的新用户望而却步。Ethereum 有限的每秒交易速度和出块速度也限制了交互的效率。这也导致投资者和开发者开始寻找更便宜、更快捷的Ethereum替代方案来承接价值外溢。
Screen 是一款能够实现多窗口远程控制的开源服务程序,简单来说就是为了解决网络异常中断或为了同时控制多个远程终端窗口而设计的程序。用户还可以使用screen服务程序同时在多个远程会话中自由切换。
MySQL复制报错,错误提示: Last_Errno: 1594 Last_Error: Relay log read failure: Could not parse relay log event entry.
v2ray服务(WebSocket+TLS+Web)在PC端客户端可以连上正常使用,但iOS手机端用shadowrocket客户端能连上,但无法上网。报错信息如下:v2ray.com/core/proxy/vmess/encoding: invalid user > v2ray.com/core/proxy/vmess: Not Found