共计 3186 个字符,预计需要花费 8 分钟才能阅读完成。
什么是服务注册发现?
对于搞微服务的同学来说,服务注册、服务发现的概念应该不会太生疏。
简略来说,当服务 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 之内置服务发现
go-zero
默认反对三种服务发现形式:
- 直连
- 基于 etcd 的服务发现
- 基于 kubernetes endpoints 的服务发现
直连
直连是最简略的形式,当咱们的服务足够简略时,比方单机即可承载咱们的业务,咱们能够间接只用这种形式。
在 rpc
的配置文件里间接指定 endpoints
即可,比方:
Rpc:
Endpoints:
- 192.168.0.111:3456
- 192.168.0.112:3456
zrpc
调用端就会调配负载到这两个节点上,其中一个节点有问题时 zrpc
会主动摘除,等节点复原时会再次调配负载。
这个办法的毛病是不能动静减少节点,每次新增节点都须要批改调用方配置并重启。
基于 etcd 的服务发现
当咱们的服务有肯定规模之后,因为一个服务可能会被很多个服务依赖,咱们就须要可能动静增减节点,而无需批改很多的调用方配置并重启。
常见的服务发现计划有 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 Endpoints 的服务发现
如果咱们的服务都是部署在 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: alpine-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
留神其中 serviceAccountName
指定该 deployment
创立进去的 pod
用哪个 ServiceAccount
。
server
和 client
都部署到 Kubernetes
集群里之后能够通过以下命令滚动重启所有 server
节点
kubectl rollout restart deploy -n adhoc server-deployment
利用如下命令查看 client
节点日志:
kubectl -n adhoc logs -f deploy/client-deployment --all-containers=true
能够看到咱们的服务发现机制完满跟进了 server
节点的变动,并且在服务更新期间没有出现异常申请。
残缺代码示例见 https://github.com/zeromicro/zero-examples/tree/main/discovery/k8s
下一篇文章我将解说在 go-zero
里如何实现基于 consul
, nacos
等的服务注册发现,敬请期待!
我的项目地址
https://github.com/tal-tech/go-zero
欢送应用 go-zero
并 star 反对咱们!
微信交换群
关注『微服务实际 』公众号并点击 交换群 获取社区群二维码。