服务发现
为什么要使用服务发现
设想下,我们写了一些通过REST API或者Thrift API调用某个服务的代码,为了发起这个请求,代码需要知道服务实例的网络地址(IP 地址和端口号)。在传统运行在物理机器上的应用中,某个服务实例的网络地址一般是静态的,比如,代码可以从只会偶尔更新的配置文件中读取网络地址。
然而在现在流行的基于云平台的微服务应用中, 有更多如下图所示的困难问题需要去解决:
1、服务实例需要动态分配网络地址;
2、服务实例可能会因为自动扩展、失败或者升级发生动态变化
因此客户端代码应该使用更加精细的服务发现机制。
在生产实践中,主要有两种服务发现机制:**客户端发现**和**服务端发现**。
客户端发现模式
当我们使用客户端发现的时候,客户端负责决定可用服务实例的网络地址并且在集群中对请求负载均衡, 客户端访问服务登记表,也就是一个可用服务的数据库,然后客户端使用一种负载均衡算法选择一个可用的服务实例然后发起请求。该模式如下图所示:
服务实例的网络地址在服务启动的时候被登记到服务注册表中,当实例终止服务时从服务注册表中移除。服务实例的注册一般是通过心中机制阶段性的时行刷新。
客户端发现机制的优势:
该模式中只增加了服务注册表,整体架构也相对简单;
客户端可以使用更加智能的,特定于应该的负载均衡机制,如一致性哈希。
客户端发现机制的缺点:
客户端发现机制中,客户端与服务注册表紧密耦合在一起,开发者必须为每一种消费服务的客户端对应的编程语言和框架版本都实现服务发现逻辑。
客户端发现模式的应用:
往往大公司会采用客户端发现机制来实现服务的发现与注册的模式。
服务器发现模式
客户端通过一个负载均衡器向服务发送请求,负载均衡器查询服务注册表并把请求路由到一台可用的服务实例上。和客户端发现一样,服务实例通过服务注册表进行服务的注册和注销。
服务端发现模式的优势和缺点:
服务端发现模式的优点:
服务发现的细节对客户端来说是抽象的,客户端仅需向负载均衡器发送请求即可。
这种方式减少了为消费服务的不同编程语言与框架实现服务发现逻辑的麻烦,很多部署环境已经提供了该功能。
服务端发现模式的缺点:
除非部署环境已经提供了负载均衡器,否则这又是一个需要额外设置和管理的可高可用的系统组件。
服务注册表
服务实例必须使用服务注册表来进行服务的注册和注销
self-registration模式
这种模式下,服务实例自己负责通过服务注册表对自己进行注册和注销,另外如果有必要的话,服务实例可以通过发送心跳包请求防止注册过期
self-registration模式有一些优势也有一些劣势:优势之一是它相对简单,而且不强制使用其他的系统组件。然而,一个很大的劣势是 它使得服务实例和服务注册表强耦合 ,你必须在每一个使用服务的客户端编程语言和架构代码中实现注册逻辑。
third-party registration
当使用third-party registration模式的时候,服务实例本身并不负责通过服务注册表注册自己,相反的,通过另一个被称作service registrar系统组件来处理注册。service registrar通过轮询或者订阅事件来检测一些运行实例的变化,当它检测到一个新的可用服务实例时就把该实例注册到服务注册表中去,service registrar还负责注销已经被终止的服务实例,
third-party registration模式也有一些优势和劣势:主要优势是使得服务从服务注册表中被解耦,你不必为开发者使用的每种开发语言和框架实现服务注册的逻辑,相反,服务实例的注册被一个专有服务以集中式的方式处理。该模式的劣势是,除非它被内置在部署环境中,不然这又是一个需要被设置和管理的高可用系统组件
总结
在一个微服务应用中,一组运行的服务实例是动态变化的,实例有动态分配的网络地址,因此,为了使得客户端能够向服务发起请求,必须要要有服务发现机制。
服务发现的关键是服务注册表,服务注册表是可用服务实例的数据库,它提供了管理和查询使用的API。服务实例使用这些管理API进行服务的注册和注销,系统组件使用查询API来发现可用的服务实例。
客户端发现的案例:Eureka、ZooKeeper
服务端发现的案例:consul+nigix
评论区