分布式应用架构体系对于业务逻辑复用的需求十分强烈,上层业务都想借助已有的底层服务,来快速搭建更多、更丰富的应用,降低新业务开展的人力和时间成本,快速满足瞬间息万变的市场需求。公共的业务被拆分出来,形成可共用的服务,最大程度地保障了代码和逻辑的复用,避免重复建设,这种设计也称为SOA(Service-Oriented Architecture)。
SOA架构中,服务消费者通过服务名称,在众多服务中找到要调用的服务的地址列表,称为服务的路由,如图1所示:
图1
而对于负载较高的服务来说,往往对应着由多台服务器组成的集群。在请求到来时,为了将请求均衡地分配到后端服务器,负载均衡程序将从服务对应的地址列表中,通过相应的负载均衡算法和规则,选取一台服务器进行访问,这个过程称为服务的负载均衡,如图2所示:
图2
当服务的规模较小时,可以采用硬编码的方式将服务地址和配置写在代码中,通过编码的方式来解决服务的路由和负载均衡问题,也可以通过传统的硬件负载均衡设备或者采用LVS或Nginx等软件解决方案,通过相关配置,来解决服务的路由和负载均衡问题,如图3所示,由于服务的机器数量在可控范围内,因此维护成本能够接受。
图3
当服务越来越多,规模越来越大时,对应的机器数量也越来越庞大,如图4所示,单靠人工来管理和维护服务及地址的配置信息,已经越来越难。并且,依赖单一的硬件负载均衡设备或者使用LVS、Nginx等软件方案进行路由和负载均衡调度,单点故障的问题也开始显现出来,一旦服务路由或者负载均衡服务器宕机,依赖它的所有服务均将失效。
图4
此时,需要一个能够动态注册和获取服务信息的地方,来统一管理服务名称和其对应的服务器列表信息,称之为服务配置中心。如图5所示,服务提供者在启动时,将其提供的服务名称、服务器地址注册到配置中心,服务消费者通过服务配置中心来获取需要调用的服务的机器列表,通过相应的负载均衡算法,选取其中一台服务器进行调用。当服务器宕机或者下线时,相应的机器需要能够动态地从服务配置中心里面移除,并能和相应的服务消费者,否则服务消费者就有可能因为调用到已经失效的服务而发生错误。在这个过程中,服务消费者只有在第一次调用服务时需要查询服务配置中心,然后将查询的信息缓存在本地,后面的调用直接使用本地缓存的服务地址列表信息,而不需要重新发起请求到服务配置中心去获取相应的服务地址列表,直到服务的地址列表有变更(机器上线或者下线)。 这种无中心化的结构解决了之前负载均衡设备所导致的单点故障问题,并且大减轻了服务配置中心的压力。
图5
基于ZooKeeper的持久和非持久节点,我们能够近乎实时地感知到后端服务器的状态(上线、下线、宕机)。通过集群间zab协议,使得服务配置信息能够保持一致。而ZooKeeper本身容错特性和leader选举机制,能保障我们方便地进行扩容。通过ZooKeeper来实现服务动态注册、机器上线与下线的动态感知,扩容方便,容错性好,且无中心性结构能够解决之前使用负载均衡设备所带来的单点故障问题,只有当配置信息更新时才会去ZooKeeper上获取最新的服务地址列表,其他时候使用本地缓存即可。