总览
服务调用整体来看就分为两步,本文以 zookeeper 作为注册中心,以及默认的 dubbo 协议讲解
- 客户端从注册中心获取远程服务地址
- 客户端通过远程服务地址发起调用
但是细分来看的话其中细节就多了,有很多需要思考的问题,本文由这些问题为引子来讲解 DUBBO 在服务调用过程的实现细节
- 服务提供者的服务以怎样的形式注册到注册中心中?
- 如果某个服务器宕机了,注册中心该如何感知才能从中删除失效的服务?
- 客户端从注册中心获取到的往往是多个服务提供者,该选择哪一个来进行调用?
- 客户端对服务端进行调用的时候又需要建立几个 TCP 连接?
- 如果注册中心挂掉了怎么办?
服务提供者将服务注册到注册中心中
假设项目 provider 目前只有 UserService 和 ProductService 这两个服务注册了,那么在 zookeeper 中它们的表现形式为
- / dubbo com.example.api.service.UserService configurators providers dubbo://10.211.55.11:20880/com.example.api.service.UserService?anyhost=true&application=user-provider&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.example.api.service.UserService&methods=deleteUser,register&pid=3906&release=2.7.5&revision=1.0.0&side=provider×tamp=1578105390062&version=1.0.0 dubbo://10.211.55.12:20880/com.example.api.service.UserService?anyhost=true&application=user-provider&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.example.api.service.UserService&methods=deleteUser,register&pid=3906&release=2.7.5&revision=1.0.0&side=provider×tamp=1578105390062&version=1.0.0 com.example.api.service.ProductService 跟上面类似
此处我们将 provider 分别部署到了 2 台机器中,它们提供的都是 UserService 和 ProductService 这两个服务,客户端会拿到 providers 然后根据负载均衡算法选择一个进行调用
消费者从注册中心获取服务进行调用
- 此时消费者要调用 register 这个接口,它从 zookeeper 中首先获取 providers 里面所有的服务列表进行缓存
- 从中挑选出满足 register 方法及参数规则要求的 provider 集合
- 然后看是否配置了路由规则,如果有的话再根据路由规则进行一次过滤,最后得到可用的服务提供者,假设没有配置路由规则,那么此时获取到的就是 10.211.55.11:20880,methods=register ... 10.211.55.12:20880,methods=register ...
- 然后根据对应的负载均衡算法挑选一个其中一个服务器的服务进行调用
- dubbo 协议默认是单连接,使用的 netty 进行通信,即默认只会存在一个 netty client(当然也可以配置多个通过 connection = ?)
- 按照 dubbo 协议来组装对应的字节码,然后将需要传输的数据实体序列化成对应的二进制字节码后放入对应的内容中进行数据传输
- 由于采用的单一 TCP 长连接数据传输,那么传输的数据量的大小将会极大的影响吞吐量
如果某台服务器宕机了怎么办
对服务提供者来说
假设 10.211.55.12 宕机或者网络故障。在 Dubbo 中与注册中心 zookeeper 建立了连接后会发送心跳信息,一旦 zookeeper 发现在指定的时间内没有收到心跳包,或者是服务端已经主动断开连接后,由于创建的 providers 中的结点都是临时结点,这个结点将会在连接断开后被自动删除
对消费者来说
消费者再从注册中心获取到所有的 provider 服务后会缓存到本地,不用每次调用的时候都从 zookeeper 中拉取。当 zookeeper 结点被删除后会通知消费者去更新可用的服务提供者列表,如果之前已经调用了失效的服务器那么会根据负载均衡策略来选择另外某台机器等进行调用
如果注册中心挂掉了怎么办
provider 从 zookeeper 获取 providers 成功后会缓存到应用内存中,此后的服务调用负载均衡算法会从内存中直接选择对应的提供者进行调用,就算注册中心挂掉了后也能够正常通信,不过服务变动情况客户端就无法得到通知了
客户端对服务端进行调用的时候又需要建立几个 TCP 连接
- 默认使用的 dubbo 协议,dubbo 协议使用的是 netty 做通信
- 默认的 connection 数为 1 即 dubbo 协议默认是单连接的
- connection 的数量决定了创建 netty client 的数量,也就是需要创建多少个 tcp 连接
- 客户端不是想创建多少就创建多少的比如 connection = 1000,这个时候再服务提供者端会进行限制,比如限制每个消费者最多创建 5 个连接,那么此时客户端只有 5 个连接