环境
- 框架:Spring Cloud Alibaba
- 运行环境:Kubernetes
- 注册中心:Nacos
问题
当在 Spring Cloud Alibaba 中使用 Dubbo 服务时,或者就是单纯的 Dubbo 服务时,会经常遇到 No Provider 的问题。
产生这个问题的一个原因是,Kubernetes 中的服务更新时,会启动新 Pod,然后关闭旧 Pod,没对 Dubbo 做任何配置的时候,注册服务时,使用的都是 Pod 容器的 IP,这个 IP 在服务更新或者重启的时候会变,Dubbo 中的长连接会重试,这时会因为 IP 变化导致无法重新连上,此时日志中就会出现大量的连接失败的信息。由于连接不上对应的服务,还会出现 No Provider。
解决方案
使用 Kubernetes 的 Service 进行注册,这样可以保证 IP 固定不变。
首先给服务配置 Service,配置后在容器中通过 $(部署名_SERVICE_HOST)
可以获取 Service 的 IP。
然后对 Dubbo 进行下面方式(以环境变量方式)的配置:
DUBBO_IP_TO_REGISTRY=$(部署名_SERVICE_HOST)
DUBBO_PROTOCOL_PORT=20880
因为使用的 Nacos 注册中心,还需要有一个配置:
SPRING_CLOUD_NACOS_DISCOVERY_IP=$(部署名_SERVICE_HOST)
此时在Nacos注册中心的服务IP就会使用 Service 的 IP。
在上图中,IP 这一列显示的值是由 SPRING_CLOUD_NACOS_DISCOVERY_IP
配置起作用的。端口 8080 是 HTTP 协议的端口,也就是 SERVER_PORT
决定的。
在元数据中,dubbo://IP:PORT
这部分的 IP 和端口是由 DUBBO_IP_TO_REGISTRY
和 DUBBO_PROTOCOL_PORT
起作用的,URL中的参数 bind.ip
的值是 Pod 的 IP,这个 IP 不会影响服务的稳定。
服务改用 Service 注册后,稳定性提高很多,和原先相比,这个方案中多了一层 Kubernetes Service 的负载均衡,当集群服务有多个实例的时候,Nacos 中始终都只会显示一个实例,做到这一步时,实际上可以考虑 Spring Cloud Kubernetes 方式的服务发现了。