Service Mesh学习(3)——注册中心如何高可用

在引入注册中心后,是否可以高枕无忧呢?先来看下一下几个问题:

Service Mesh学习(3)——注册中心如何高可用_第1张图片

图中问题主要分为两类,对注册中心数据的信任问题以及节点频繁导致的广播风暴问题。

在传统的观念中,我们肯定会选择信任引入的第三方基础设施,比如 MySQL 、Redis ,这种数据层的中间件,我们肯定是要完全信任其中的数据的。但对于注册中心,信任推送数据的风险非常大。

1. 注册中心完全故障了,服务是否还能正常访问?

注册中心完全故障的情况,是很常见的。在程序进程中缓存访问服务的节点,几乎是一件必然的事情,不能每个请求都去注册中心拿相应服务的注册信息。

所以只要在进程中缓存服务的节点,影响就会可控。但是,当注册中心完全故障的时候,服务注册功能是失效的此时的扩容操作无法进行。如果在容器中,因为 Pod(一组容器的集合) 滚动升级的原因造成先启动新的Pod,一定要在程序启动注册失败时抛出异常,使程序无法启动,否则容器 IP 的变化也会导致服务的访问异常。

2. 注册中心因为高负载,推送了异常的数据,服务是否还能正常访问?

如果服务节点不是特别多,很难遇到这个问题,但随着微服务规模的增大,注册中心很有可能遇到瓶颈。一旦出现高负载,会使服务和注册中心之间的健康检查或保活出现问题,注册中心使节点异常下线,只推送部分节点数据到订阅的服务。

这个问题看似不严重,但一旦推送了过少的节点到服务,会导致主调服务打挂被调服务,长时间不能恢复,甚至会导致整个微服务集群雪崩。

如何解决这种问题呢?

可以在客户端的服务发现 SDK 中加入自我保护机制:一旦服务的节点数量下降超过一定阈值,就进入自我保护状态,放弃使用新推送过来的服务注册信息

3. 新加入的机器,出现了网络连通性问题(注册中心和机器网络正常,但服务机器之间网络异常),应该怎样应对?

实际上网络连通性问题是比较容易发生的,往往出于安全考虑,各个部门之间可能会处在不同的 VPC(私有网络) ,但现实中又有互相访问的情况,一旦网络规则维护不好,很容易出现新添加的机器注册中心的网段可以访问,但是服务之间却无法访问的情况。在注册中心的使用场景中,网络故障是最优先考虑的问题,如果发生了分区故障,问题 2 描述的情况也会发生。

如何解决此类问题呢?

这个就要发挥负载均衡器模块的作用了:在负载均衡中可以加入被动健康检查(节点熔断)和主动健康检查来在客户端主动剔除失效的节点

4. 服务是否应该完全信任注册中心推送的数据?

对于这个问题,比较好的做法就是采用 Service Mesh 数据面之一 Envoy:相比注册中心的数据,更信任本地数据,所以 Envoy 设计了 2×2 矩阵来决定节点是否应该路由。

发现状态 健康检查成功 健康检查失败
发现 路由 不要路由
未发现 路由 不要路由,删除

如上表所示,只有在健康检查失败和注册中心未发现的情况才会删除节点,只要健康检查成功,无论是否发现此节点,都会路由。

实际上采用了这种方式,前面的三个问题,都可以迎刃而解了。当然实现一个健壮的负载均衡器可没这么简单,还有很多边缘情况你需要考虑,具体内容将会在后面的负载均衡器中详细展开。

5. 服务发布后,节点频繁变更造成 N×M 次事件通知,形成广播风暴,该如何解决?

前面四个问题都解决了,第 5 个问题即便出现了,它对线上服务的影响也非常小。但如何避免问题 5 的发生呢?

实际上此问题也可能导致问题 2 的发生。大量广播事件的发生,挤占网络带宽,甚至会导致网络带宽占满,此时注册中心和服务间的健康检查或保活,都会因为带宽不足造成信息丢失,使注册中心推送错误的数据。

如何解决此类问题呢?

其实很简单,可以将事件消息合并推送。在 Istio 的 Pilot 的模块中,实现了一种合并机制,100ms 内有新的事件消息时,便会继续等待下一条,最多等待 1s,当然时间的参数是可以配置的,这里说的是默认参数。

虽然这个解决方案会影响事件通知的时效性,但相对于收益来说,它是一个非常好的解决方案,可想而知,如果进一步增加时效性,那么付出的研发成本和机器资源成本都将呈指数级增加,显然是得不偿失的。

Service Mesh 中的注册中心

实际上在 Service Mesh 方案中,服务节点发现的问题用传统的注册中心方案也是可以解决的,但如果涉及 Kubernetes 和 ECS 跨集群访问,最好还是支持 Envoy 定义的 xDS 协议中的 EDS 协议。EDS是 endpoint discovery service 的缩写,无论是 Istio,还是最新版本的 gRPC,都已经默认支持了 EDS 协议,可以说EDS 实际上已经是服务发现的规范了。

在 Service Mesh 方案中,因为大多是和 Kubernetes 集群结合的方案,所以你要特别注意发版或者自动扩缩容引起的节点 IP 变化的问题。节点的频繁变化,对注册中心的健壮性提出了更高的要求,这些问题我在本讲前半部分已经详细说过了,这里就不再赘述了。

除了用传统的注册中心组件外,Kubernetes 内部的发现机制在 Service Mesh 中也得到了广泛应用,例如 Istio通过监听 Kubernetes Pod 的变化,实现服务发现的功能,这样就不需要服务自身来做服务注册了。

那么 Service Mesh 中实现的注册发现功能,相比传统微服务有哪些优势呢?

1. 无须服务自身注册,由 sidecar 代理注册

sidecar 通过接受控制面下发的配置信息,进行服务注册。相对于服务自身注册,这样可以减少服务自身开发的工作量同时也很容易做到注册的配置信息一致化。比如如果服务自己注册,其实很难控制服务注册的 metadata 信息,在 SDK 中很难约束和升级,比如运行环境、地域、健康检查方式等。

sidecar 代理还带来了可以随时更新 meta 信息的好处。在传统的 SDK 模式中,想要动态调整服务的权重、metadata 等信息的时候,需要重新发布版本,或者依靠配置中心的能力,但这些控制信息往往散落在各个服务中,不方便管理,在 Service Mesh 中只需要依靠控制面的能力,就可以轻松做到了。

2. 通过控制面聚合多种、多个注册中心数据

像 Istio 的 pilot 模块,在 1.1 版本就支持了单控制面多集群的功能,通过 pilot 将多个注册中心的数据聚合,可以有效降低单一注册中心的读写压力,使注册中心更容易水平扩展

比如在实践中,将多个 Consul 数据中心的数据通过 pilot 模块聚合,然后提供 xDS 协议,供服务发现使用,实现了虚拟机到 Kubernetes 环境的无缝迁移。

3. 通过 sidecar 提供服务正确性 check 功能

在注册中心中,有一种健康检查方式是注册中心主动 ping 服务的模式。实际上如果服务 IP 发生变化,又用了同样的 ping 接口时,健康检查会出现错误。而通过 sidecar 模式,当发现服务 ping 接口过来的流量时,进行服务名称的检测,通过 header 中增加服务名称与本地服务名称做校验的方式进行检测,可以有效避免这样的错误

你可能感兴趣的:(微服务,高可用注册中心)