0104-微服务体系结构中的服务发现
为什么使用服务发现?
假设您正在编写一些调用具有REST API或Thrift API的服务的代码。为了提出请求,您的代码需要知道服务实例的网络位置(IP地址和端口)。在运行在物理硬件上的传统应用程序中,服务实例的网络位置相对静态。例如,您的代码可以从偶尔更新的配置文件中读取网络位置。
然而,在现代的基于云的微服务应用中,这是一个更难以解决的问题,如下图所示。
服务实例具有动态分配的网络位置。而且,由于自动调节,失败和升级,服务实例集动态地改变。因此,您的客户端代码需要使用更复杂的服务发现机制。
有两种主要的服务发现模式:客户端发现和服务器端发现。我们先来看看客户端的发现。
客户端发现模式
在使用客户端发现时,客户端负责确定可用服务实例的网络位置以及它们之间的负载均衡请求。客户端查询服务注册表,该服务注册表是可用服务实例的数据库。客户端然后使用负载平衡算法来选择可用服务实例之一并发出请求。
下图显示了此模式的结构。
服务实例的网络位置在启动时向服务注册表注册。实例终止时,它将从服务注册表中删除。服务实例的注册通常使用心跳机制定期刷新。
Netflix OSS提供了客户端发现模式的一个很好的例子。Netflix Eureka是一个服务注册表。它提供了一个REST API来管理服务实例注册和查询可用实例。Netflix Ribbon是一个IPC客户端,与Eureka一起在可用服务实例间负载平衡请求。我们将在本文后面更深入地讨论Eureka。
客户端发现模式具有各种优点和缺点。这种模式比较简单,除服务注册表外,没有其他移动部分。此外,由于客户端知道可用的服务实例,因此可以制定智能的,特定于应用程序的负载平衡决策,例如始终使用散列。这种模式的一个显着缺点是它将客户端与服务注册表相连接。您必须为服务客户端使用的每种编程语言和框架实现客户端服务发现逻辑。
现在我们已经研究了客户端发现,让我们来看看服务器端发现。
服务器端发现模式
服务发现的另一种方法是服务器端发现模式。下图显示了此模式的结构。
客户端通过负载平衡器向服务器发出请求。负载均衡器查询服务注册表并将每个请求路由到可用的服务实例。与客户端发现一样,服务实例也会注册到服务注册中心并注销。
的AWS弹性负载均衡(ELB)是一个服务器端发现路由器的一个例子。ELB通常用于负载平衡来自Internet的外部流量。但是,您也可以使用ELB来负载均衡虚拟私有云(VPC)内部的流量。客户端使用其DNS名称通过ELB发出请求(HTTP或TCP)。ELB负载在一组已注册的弹性计算云(EC2)实例或EC2容器服务(ECS)容器之间平衡流量。没有单独的服务注册表。相反,EC2实例和ECS容器是在ELB本身注册的。
HTTP服务器和负载平衡器(如NGINX Plus和NGINX)也可以用作服务器端发现负载平衡器。例如,这篇博文描述了使用Consul模板动态重新配置NGINX反向代理。Consul模板是一个工具,可以定期从存储在Consul服务注册表中的配置数据中重新生成任意配置文件。只要文件发生变化,它就会运行任意的shell命令。在博客帖子描述的例子中,Consul模板生成一个nginx.conf文件,它配置反向代理,然后运行一条命令告诉NGINX重新加载配置。更复杂的实现可以使用HTTP API或DNS动态重新配置NGINX Plus 。
某些部署环境(例如Kubernetes和Marathon)在群集中的每个主机上运行代理。代理扮演服务器端发现负载平衡器的角色。为了向服务发出请求,客户端使用主机的IP地址和服务分配的端口通过代理路由请求。然后,代理将请求透明地转发到集群中某处运行的可用服务实例。
服务器端发现模式有几个好处和缺点。这种模式的一大优点是,发现的细节从客户端抽象出来。客户只需向负载均衡器发出请求。这消除了为您的服务客户端使用的每种编程语言和框架实现发现逻辑的需要。另外,如上所述,某些部署环境免费提供此功能。然而,这种模式也有一些缺点。除非负载平衡器由部署环境提供,否则它是您需要设置和管理的另一个高度可用的系统组件。
服务注册表
该服务注册表是服务发现的一个关键部分。它是一个包含服务实例的网络位置的数据库。服务注册表需要高度可用并且是最新的。客户端可以缓存从服务注册表中获取的网络位置。但是,这些信息最终会过时,客户端将无法发现服务实例。因此,服务注册表由一组使用复制协议来维护一致性的服务器组成。
如前所述,Netflix Eureka是服务注册表的一个很好的例子。它提供了用于注册和查询服务实例的REST API。服务实例使用POST
请求注册其网络位置。每30秒钟,它必须使用PUT
请求刷新其注册。通过使用HTTP DELETE
请求或实例注册超时来删除注册。正如您所料,客户端可以通过使用HTTP GET
请求来检索已注册的服务实例。
Netflix通过在每个Amazon EC2可用区中运行一台或多台Eureka服务器,实现高可用性。每个Eureka服务器在具有弹性IP地址的EC2实例上运行。DNS TEXT
记录用于存储尤里卡群集配置,该配置是从可用区域到尤里卡服务器的网络位置列表的映射。当Eureka服务器启动时,它会查询DNS以检索Eureka群集配置,找到其对等点,并为自己分配一个未使用的弹性IP地址。
尤里卡客户 - 服务和服务客户 - 查询DNS以发现尤里卡服务器的网络位置。客户更喜欢在同一个可用区域使用Eureka服务器。但是,如果没有可用的客户端使用另一个可用区域中的Eureka服务器。
服务注册的其他例子包括:
- etcd - 用于共享配置和服务发现的高可用性,分布式,一致的键值存储。两个使用etcd的着名项目是Kubernetes和Cloud Foundry。
- consul - 发现和配置服务的工具。它提供了一个API,允许客户注册和发现服务。领事可以执行健康检查以确定服务可用性。
- Apache Zookeeper - 用于分布式应用程序的广泛使用的高性能协调服务。Apache Zookeeper最初是Hadoop的一个子项目,但现在是一个顶级项目。
另外,如前所述,某些系统(如Kubernetes,Marathon和AWS)没有明确的服务注册表。相反,服务注册表只是基础架构的一个内置部分。
现在我们已经看了服务注册表的概念,让我们看看服务实例是如何在服务注册表中注册的。
服务注册选项
如前所述,服务实例必须向服务注册中心注册和注销。有几种不同的方式来处理注册和注销。一种选择是服务实例注册自己,即自注册模式。另一个选项是其他系统组件管理服务实例的注册,第三方注册模式。我们先来看看自注册模式。
自注册模式
当使用自注册模式时,服务实例负责注册和注销服务注册表本身。此外,如果需要,服务实例会发送心跳请求以防止其注册过期。下图显示了此模式的结构。
Netflix OSS Eureka客户端就是这种方法的一个很好的例子。尤里卡客户端处理服务实例注册和注销的所有方面。在春天的云项目,它实现了各种图案,包括服务发现,可以很容易地与尤里卡自动注册服务实例。您只需使用注释来注释Java配置类@EnableEurekaClient
。
自注册模式具有各种优点和缺点。一个好处是它相对简单并且不需要任何其他系统组件。然而,其主要缺点是它将服务实例连接到服务注册表。您必须在您的服务使用的每种编程语言和框架中实施注册码。
另一种将服务与服务注册表分离的方法是第三方注册模式。
第三方注册模式
在使用第三方注册模式时,服务实例不负责向服务注册中心注册自己。相反,另一个称为服务注册商的系统组件处理注册。服务注册机构通过轮询部署环境或订阅事件来跟踪对运行实例集的更改。当它注意到新近可用的服务实例时,它会向服务注册中心注册该实例。服务注册商也注销已终止的服务实例。下图显示了此模式的结构。
服务注册商的一个例子是开源注册商项目。它会自动注册和注销部署为Docker容器的服务实例。注册人支持多个服务注册管理机构,包括etcd和Consul。
服务注册商的另一个例子是NetflixOSS Prana。主要用于使用非JVM语言编写的服务,它是与服务实例并排运行的边车应用程序。Prana使用Netflix Eureka注册和注销服务实例。
服务注册器是部署环境的内置组件。自动缩放组创建的EC2实例可以自动注册到ELB。Kubernetes服务会自动注册并可用于发现。
第三方注册模式具有各种优点和缺点。一个主要好处是服务与服务注册表分离。您无需为开发人员使用的每种编程语言和框架都实施服务注册逻辑。相反,服务实例注册是在专用服务中以集中方式处理的。
这种模式的一个缺点是,除非它构建在部署环境中,否则它是您需要设置和管理的又一个高度可用的系统组件。
概要
在微服务应用程序中,运行服务实例集动态变化。实例已动态分配网络位置。因此,为了使客户端对服务发出请求,它必须使用服务发现机制。
服务发现的关键部分是服务注册表。服务注册表是可用服务实例的数据库。服务注册表提供了一个管理API和一个查询API。服务实例使用管理API向服务注册中心注册和注销。查询API由系统组件用来发现可用的服务实例。
有两种主要的服务发现模式:客户端发现和服务端发现。在使用客户端服务发现的系统中,客户端查询服务注册表,选择一个可用实例并发出请求。在使用服务器端发现的系统中,客户端通过路由器发出请求,路由器查询服务注册表并将请求转发给可用实例。
服务实例向服务注册中心注册和注销有两种主要方式。一种选择是服务实例向服务注册中心注册自己的自注册模式。另一个选项是其他系统组件代表服务处理注册和注销,第三方注册模式。
在某些部署环境中,您需要使用服务注册表(如Netflix Eureka,etcd或Apache Zookeeper)设置您自己的服务发现基础结构。在其他部署环境中,内置了服务发现。例如,Kubernetes和Marathon处理服务实例注册和注销。他们还在每个扮演服务器端发现路由器角色的群集主机上运行代理。
HTTP反向代理和负载均衡器(如NGINX)也可以用作服务器端发现负载平衡器。服务注册中心可以将路由信息推送到NGINX并调用正常的配置更新; 例如,您可以使用Consul模板。NGINX Plus支持额外的动态重新配置机制 - 它可以使用DNS从注册表中提取有关服务实例的信息,并提供用于远程重新配置的API。