04-服务发现

原文链接

这是我们系列中关于使用微服务构建应用程序的第四篇文章。在本文中,我们将探讨与服务发现密切相关的问题。

为何需要服务发现

让我们假设正在编写一些代码来调用具有REST API或Thrift API的服务。为了发出请求,代码需要知道服务实例的网络位置(IP地址和端口)。

  • 在物理硬件上运行的传统应用程序中,服务实例的网络位置是相对静态的。例如,代码可以从偶尔更新的配置文件中读取网络位置。
  • 在现代的基于云的微服务应用程序中,这是一个难以解决的问题,如下图所示。

image

服务实例具有动态分配的网络位置。此外,由于自动扩展,故障和升级,服务实例集会动态更改。因此,客户端代码需要使用更复杂的服务发现机制。有两种主要的服务发现模式:

  • 客户端发现
  • 服务器端发现

我们先来看看客户端发现。

客户端发现模式

使用客户端发现时,客户端负责确定可用服务实例的网络位置以及跨这些实例的负载均衡请求。客户端查询服务注册表,该服务注册表是可用服务实例的数据库。然后,客户端使用负均衡算法选择一个可用的服务实例并发出请求。下图显示了此模式的结构。

image

服务实例的网络位置在启动时向服务注册表注册。实例终止时,它将从服务注册表中删除。通常使用心跳机制定期刷新服务实例的注册。

Netflix OSS提供了客户端发现模式的一个很好的例子。Netflix Eureka是一个服务注册表。它提供了一个REST API,用于管理服务实例注册和查询可用实例。Netflix Ribbon是一个IPC客户端,与Eureka一起在可用服务实例之间加载均衡请求。我们将在本文后面更深入地讨论Eureka。

客户端发现模式具有各种优点:这种模式相对简单,除了服务注册表之外,没有其他移动部件。所以,当客户端知道了可用的服务实例后,就可以进行智能的、基于特定应用程序的负载均衡决策算法(例如,使用一致性哈希算法)来访问服务。

这种模式的一个重要缺点是:它将客户端与服务注册表耦合在一起,必须为服务使用的每种编程语言和框架实现客户端服务发现逻辑。

现在我们已经了解了客户端发现,让我们来看看服务器端发现。

服务器端发现模式

服务发现的另一种方法是服务器端发现模式。下图显示了此模式的结构。

image

客户端通过负载均衡器向服务发出请求。负载均衡器查询服务注册表并将每个请求路由到可用的服务实例。与客户端发现一样,服务实例在服务注册表中注册或注销。

AWS Elastic Load Balancer(ELB)是服务器端发现路由器的示例。ELB通常用于对来自Internet的外部流量进行负载均衡。但是,也可以使用ELB来均衡虚拟私有云(VPC)内部的流量。客户端使用其DNS名称通过ELB发出请求(HTTP或TCP)。 ELB负载均衡一组已注册的弹性计算云(EC2)实例或EC2容器服务(ECS)容器之间的流量。不需要单独的服务注册表。相反,EC2实例和ECS容器已在ELB中注册完成。

HTTP服务器和负载均衡器(如NGINX Plus和NGINX)也可用作服务器端发现负载均衡器。例如,这篇博文描述了使用Consul Template动态重新配置NGINX反向代理。

Consul Template是一种工具,可定期从存储在Consul服务注册表中的配置数据中重新生成配置文件。每当文件更改时,它都会运行shell命令。

在博客文章描述的示例中,Consul Template生成一个nginx.conf文件,该文件用于配置反向代理,然后运行一个命令使NGINX重新加载配置。更复杂的实现可以使用HTTP API或DNS动态重新配置NGINX Plus。

某些部署环境(如Kubernetes和Marathon)在群集中的每个主机上运行一个代理服务。代理服务作为服务器端发现模式负载均衡器使用。为了向服务发出请求,客户端使用主机的IP地址和端口通过代理服务路由请求。然后,代理将请求透明地转发到在群集中某处运行的可用服务实例。

服务器端发现模式的优势和不足:

  • 这种模式的一个很大好处是服务发现的细节被抽象出客户端。客户端只是向负载均衡器发出请求。这消除了为服务端使用的每种编程语言和框架实现发现逻辑的需要,并且在某些部署环境(如,kubernetes和Marathon)免费提供此功能。
  • 这种模式也有一些缺点。除非部署环境提供负载均衡器,否则它是需要设置和管理的另一个高可用性系统组件。

服务注册表

服务注册表是服务发现的关键部分,它是一个包含服务实例网络位置的数据库。服务注册表需要具有高可用性数据最新性

客户端可以缓存从服务注册表获取的网络位置,但是,该信息最终会过时而导致客户端无法发现服务实例。服务注册表由一组服务组成,这些服务器通过复制协议来保持数据的一致性。

如前所述,Netflix Eureka是服务注册表的一个很好的例子。它提供了一个REST API,用于注册和查询服务实例。

  • 服务实例使用HTTP POST请求注册其网络位置。每隔30秒,它必须使用HTTP PUT请求刷新注册信息
  • 通过使用HTTP DELETE请求来删除注册信息,当实例注册超时,也会自动删除注册信息
  • 客户端可以使用HTTP GET请求检索已注册的服务实例

Netflix通过在每个Amazon EC2可用区域中运行一个或多个Eureka服务器来实现高可用性。每个Eureka服务器都在具有弹性IP地址的EC2实例上运行。DNS TEXT记录用于存储Eureka群集配置,该配置是从可用区域到Eureka服务器的网络位置列表的映射。当Eureka服务器启动时,它会查询DNS以检索Eureka群集配置,找到其对等端,并为自己分配未使用的弹性IP地址。

Eureka客户端通过查询DNS来发现Eureka服务器的网络位置。客户端更希望在同一可用区中使用Eureka服务器,但是,如果在同一个可用区内没有可访问的Eureka服务器,那么客户端会在另一个可用区中访问Eureka服务器。

服务注册表的其他示例包括:

  • etcd:用于共享配置和服务发现的高可用的、分布式的、一致性的键值对存储。使用etcd的两个值得注意的项目是Kubernetes和Cloud Foundry。
  • consul:用于发现和配置服务的工具。它提供了一个API,允许客户注册和发现服务。Consul可以执行运行状况检查以确定服务可用性。
  • Apache Zookeeper:一种广泛使用的高性能协调服务,适用于分布式应用程序。

此外,如前所述,某些系统(如Kubernetes,Marathon和AWS)没有明确的服务注册表。服务注册表只是基础结构的内置部分。现在我们已经了解了服务注册表的概念,让我们看看如何在服务注册表中注册服务实例。

服务注册选项

如前所述,服务实例必须在服务注册表中注册和注销。有几种不同的方式来处理注册和注销。

  1. 服务实例自我注册,即自注册模式
  2. 用于某些其他系统组件来管理服务实例的注册,即第三方注册模式

自注册模式

使用自注册模式时,服务实例负责向服务注册表注册和注销自身,如果需要,服务实例会发送心跳请求以防止其注册过期。下图显示自注册模式的结构。

image

这种方法的一个很好的例子是Netflix OSS Eureka客户端,它会处理服务实例注册和注销的所有方面。Spring Cloud项目实现了各种模式,包括服务发现,可以轻松地使用Eureka自动注册服务实例。只需使用@EnableEurekaClient批注对Java Configuration类进行批注。

自注册模式的优缺点:

  • 好处:它相对简单并且不需要任何其他系统组件。
  • 缺点:它将服务实例耦合到服务注册表,必须在服务使用的每种编程语言和框架中实现注册代码。

将服务与服务注册表分离的替代方法是第三方注册模式。

第三方注册模式

使用第三方注册模式时,服务实例不负责向服务注册表注册自己。相反,另一个称为服务注册器的系统组件处理注册。服务注册器通过轮询部署环境或订阅事件来跟踪运行实例集的更改。当它发现有新的服务实例运行时,会将新的服务实例注册到服务注册表中,同时,服务注册器还负责注销已终止运行的服务实例。下图显示了此模式的结构。

image

服务注册器的例子:

  1. Registrator:它会自动注册和注销部署为Docker容器的服务实例。Registrator支持多个服务注册表,包括etcd和Consul。
  2. NetflixOSS Prana:它主要用于以非JVM语言编写的服务,它是一个与服务实例并行运行的sidecar应用程序。Prana使用Netflix Eureka注册和注销服务实例。

服务注册器是部署环境的内置组件。由Autoscaling Group创建的EC2实例可以自动注册到ELB。Kubernetes的services会自动注册并被发现。

第三方注册模式的优缺点:

  • 好处:服务与服务注册表分离。不需要为开发人员使用的每种编程语言和框架实现服务注册逻辑。相反,服务实例注册在专用服务中以集中方式处理。
  • 缺点:除非它内置于部署环境中,否则它是需要设置和管理的另一个高可用性系统组件。

总结

在微服务应用程序中,正在运行的服务实例集合会动态更改,每个服务实例都会动态分配网络位置。因此,客户端要向服务实例发出请求,就必须使用服务发现机制。

服务发现的关键部分是服务注册表,它是可用服务实例的数据库,提供管理API查询API

  • 使用管理API在服务注册表中注册和注销服务实例
  • 使用查询API来发现可用的服务实例

有两种主要的服务发现模式

  • 在使用客户端发现的系统中,客户端查询服务注册表,选择可用实例并发出请求。
  • 在使用服务端发现的系统中,客户端通过负载均衡器发出请求,负载均衡器查询服务注册表并将请求转发给可用实例。

服务实例在服务注册表中注册和注销有两种主要方式:

  • 自注册模式:服务实例向服务注册表进行注册和注销
  • 第三方注册模式:某些其他系统组件代表服务处理注册和注销

在某些部署环境中,需要使用服务注册表(如Netflix Eureka,etcd或Apache Zookeeper)作为服务发现基础组件。

在其他部署环境中,内置了服务发现。例如,Kubernetes和Marathon自带处理服务实例注册和注销的功能,它们在每台主机上运行一个代理服务器作为服务器端发现模式中的负载均衡器。

HTTP反向代理和负载均衡器(如NGINX)也可用作服务器端发现模式中的负载均衡器。服务注册表可以将路由信息推送到NGINX并调用正常的配置更新;例如,可以使用Consul Template。NGINX Plus支持其他动态重新配置机制,它可以使用DNS从注册表中提取有关服务实例的信息,并提供用于远程重新配置的API。在未来的博客文章中,我们将继续深入研究微服务的其他方面。

上次修改: 14 April 2020