本文出自Service Discovery in a Microservices Architecture,作者 Chris Richardson, 写于2015年5月19日

这是本系列文章的第四篇。

本文我们继续探索与服务发现紧密联系的有关问题。

一、为什么使用服务发现?

想象一下编写代码调用REST或者Thrift API的服务,为了实现这个调用,你的代码需要知道服务实例的网络位置(IP 地址和端口)。在运行在物理硬件的传统应用中,服务实例的网络位置是相对静止的。例如,代码可以从配置文件中读取网络位置,这个配置文件偶尔会更新。

但是,在现代基于云的微服务应用中,这是非常难以解决的问题,正如图4-1显示的一样:

服务实例被动态地赋予网路位置。另外,由于自动伸缩、故障和升级,服务实例集合经常会动态改变。所以客户端代码需要使用详细设计的服务发现机制。

这里写图片描述

图4-1 客户端或者API网关需要帮助发现服务

有两种主要的服务发现机制:客户端发现机制服务端发现机制。首先来看一下客户端发现机制。

二、客户端发现模式

当使用客户端发现模式时,客户端负责确定可用服务实例的网络位置并且对通过它们的请求进行负载均衡客户端查询服务注册中心,服务注册中心是一个可用服务实例的数据库。客户端接着使用负载均衡算法选择可用的服务实例中的一个并把这个请求路由到该实例

图4-2显示这个模式的结构:

这里写图片描述

图4-2 客户端执行服务发现的任务

当服务实例启动的时候,它的网络地址被注册到服务注册中心。当该实例终止的时候,该地址从服务注册中心移除服务实例的注册通常使用心跳机制定期刷新

Netflix OSS 为客户端发现模式提供了很好的例证。Netflix Eureka 是一个服务注册中心,它提供了REST API来管理服务实例的注册和可用实例的查询。Netflix Ribbon是一个和Eureka共同工作的IPC客户端,它负责将请求负载均衡到可用的服务实例上。后面我们会深入讨论Eureka。

客户端发现模式有很多的缺点和优点。

优点:

  • 这个模式相对更直接一点,除了服务注册中心,没有要改变的地方;
  • 并且,因为客户端了解可用的服务实例,它能做出智能、针对特定应用的负载均衡决策,比如使用一致性哈希。

缺点:

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

了解了客户端发现机制,让我们继续探索一下服务端发现模式。

三、服务端发现模式

另外一种到服务注册中心的途径是服务端发现模式 。图4-3 显示了这种模式的结构。

这里写图片描述

图4-3 服务注册中心也可以由服务器处理

客户端通过负载均衡器向服务发送请求负载均衡器查询服务注册中心并路由每个请求到可用的服务实例。与客户端发现机制一样,服务实例也需要向服务注册中心注册和注销

AWS Elastic Load Balancer (ELB) 是服务端发现路由器的一个例证。ELB通常用来对外部的因特网流量进行负载均衡。但是,你也可以在内部使用ELB进行到虚拟私有云(virtual private cloud ,VPC)的负载均衡。

客户端使用ELB的域名来发送HTTP或者TCP请求。ELB将流量负载均衡地路由到一系列注册的Elastic Compute Cloud (EC2)实例,或者EC2 Container Service (ECS) 容器。不存在独立可见的服务注册中心。EC2实例和ECS容器直接注册到ELB本身。

HTTP服务器和负载均衡器,比如NGINX Plus和NGINX,也可以用作服务端发现机制中的负载均衡器。例如,这篇文章描述了使用Consul Template动态地更新NGINX反向代理服务器的配置。Consul Template是一个可以根据存储在Consul service registry的数据定期重新生成任意配置文件的工具。无论什么时候文件改变,它都会运行任意的shell命令。在上面的文章中描述的例子中,Consul Template生成了一个nginx.conf的配置文件,用于配置反向代理,接着运行命令告诉NGINX重新加载该配置文件。一个更加复杂的实现,比如使用NGINX的HTTP API或者DNS也能动态地更新NGINX Plus的配置 。

一些部署环境,比如KubernetesMarathon在集群的每个主机上都会运行代理。代理扮演服务端发现机制中的负载均衡器的角色。为了给服务发请求,客户端通过代理使用主机IP和服务的端口号路由请求。代理接着转发该请求到运行在集群上的可用服务实例。

服务端发现模式有几个优点和缺点。

优点:

  • 服务发现的细节从客户端抽象出来,客户端只需要给负载均衡器发请求即可。这种方式避免为服务客户端使用的每种编程语言和框架都实现服务发现逻辑;
  • 正如上文所说,一些部署环境免费提供了这种功能

缺点:

  • 除非部署环境提供负载均衡器,否则它又是另一个需要设置和管理的高度可用的系统组件

四、服务注册中心

服务注册中心是服务发现机制中的核心部分。它是一个包含服务实例网络位置的数据库。服务注册中心需要高度可用并实时更新。客户端可以缓存从服务注册中心获取的网络位置。但是,信息最终会过期,导致客户端不能发现服务实例。于是,服务注册中心可以使用复制协议来维护一致性的服务器集群。

上文提到,Netflix Eureka是服务注册中心的很好的例证。它提供REST API来注册和查询服务实例。服务实例通过POST请求来注册它的网络地址,每隔30s,它都要通过PUT请求来刷新它的注册信息。当服务实例发送HTTP 的DELETE请求,或者注册(包括刷新)超时的时候,该注册信息都会从服务注册中心移除。如你所想,客户端可以通过使用HTTPGET请求来获取已经注册的服务实例。

Netflix通过在每个Amazon EC2可用区域运行一个或者多个Eureka服务器来实现高可用性。每个Eureka服务器运行在有弹性IP地址的EC2实例上。使用DNSTEXT记录来存储Eureka集群的配置,这个配置是从可用区域到Eureka服务器的网络地址的列表的映射表,当Eureka服务器启动的时候,它查询DNS来获取Eureka集群配置,定位它的伙伴,分配给自己一个没有使用的弹性IP地址

Eureka客户端、服务和服务客户端通过查询DNS来发现Eureka服务器的网络地址。客户端更希望使用在相同可用区域里的Eureka服务器。但是,如果没有可用的,就需要使用别的可用区域的里的Eureka服务器。

服务注册中心的其他例子:

  • etcd:高度可用,分布式,一致性的键值存储,用来共享配置或作为服务注册中心。Kubernetes和Cloud Foundry 这两个著名的项目使用了它;
  • Consul:一个发现和配置服务的工具,提供了API允许客户端注册并发现服务,也能通过健康检查来确定服务的可用性;
  • Apache ZooKeeper:用于分布式应用的广泛使用的、高性能的协调服务。开始作为Hadoop的子项目,但是现在是一个独立的顶级项目;

正如前面提到的,一些系统,比如Kubernetes,Marathon和AWS不需要显式的服务注册中心,而是作为基础设施的内置的一部分。

我们已经了解了服务注册中心的概念,继续看看服务实例是如何注册到服务注册中心的。

五、服务注册选项

如上所述,服务实例必须从服务注册中心注册和注销。有很多种方式可以处理注册和注销操作:

首先看一下自我注册模式。

5.1自我注册模式

当使用自我注册模式时,服务实例自己负责从服务注册中心注册和注销。并且如果必要的话,服务实例要发送心跳请求来防止注册过期。图4-4显示了这种模式的结构:

这里写图片描述

图4-4 服务可以自己完成注册

这种方法的一个例证是Netflix OSS Eureka client 。Eureka client可以处理服务实例注册和注销的所有方面的事情。Spring Cloud project 实现了多种模式,包括服务注册中心,使得自动注册服务实例到Eureka很容易。你只要在Java配置类中添加@EnableEurekaClient注解即可。

自我注册模式也有很多优点和缺点。

优点:

  • 相对简单,并且不要求额外的系统组件;

缺点:

  • 将服务实例和服务注册中心耦合,导致为服务使用的每种编程语言和框架都实现服务注册逻辑;

可以替代的方法是第三方注册模式,它将服务和服务注册中心解耦,

5.2第三方注册模式

当使用第三方注册模式时,服务实例不负责注册自己到服务注册中心。 而是通过其他称为服务注册组件的系统组件来处理服务注册。服务注册组件通过轮询部署环境或者订阅事件来追踪运行实例的集合的变化。当它注意到有新的可用的服务实例时,就会将该实例注册到服务注册中心。服务注册组件也可以注销终止的服务实例。

图4-5 显示了这种模式的结构:

这里写图片描述

图4-5 独立的注册组件服务负责注册其他的服务

服务注册组件的一个例证是开源的Registrator工程。它会自动的注册和注销部署为Docker容器的服务实例。注册组件支持多种服务注册中心,比如etcd和Consul。

另外一个服务注册中心的例证是NetflixOSS Prana 。主要用于非JVM语言编写的服务,它是一个和服务实例并行运行的sidecar应用。Prana使用Netflix Eureka来注册和注销服务实例。

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

第三方注册模式也有很多的缺点和优点。

优点:

  • 一个主要的优点是服务与服务注册中心解耦,不需要为服务使用的每种编程语言和框架都实现服务注册逻辑。服务注册逻辑通过一个专门的服务以集中的方式处理;

缺点:

  • 除非该注册组件在部署环境中内建,需要设置和管理一个高可用的系统组件

六、总结

在微服务架构中,运行的服务实例集合是动态变化的。实例也被动态的赋予网络地址。于是为了客户端能够给服务发送请求,就必须使用服务发现机制。

服务发现机制中的核心部分是服务注册中心。服务注册中心是可用服务实例的数据库。服务注册中心提供管理API和查询API。服务实例使用管理API从服务注册中心注册和注销。系统组件使用查询API来发现可用的服务实例。

服务从服务注册中心注册和注销有两种方式:

在一些部署环境中,需要使用比如Netflix Eureka, etcd, 或者Apache ZooKeeper等设置自己的服务发现基础设施。在一些其他的部署环境中,服务发现机制是内建的。例如,KubernetesMarathon自己处理服务的注册和注销。它们也在每个集群主机上运行一个代理,这个集群主机扮演了服务端发现机制中的路由器的角色。

HTTP 反向代理和负载均衡器比如NGINX也能用作服务端发现种的负载均衡器。服务注册中心可以给NGINX推送路由信息并且优雅的完成配置更新。例如可以使用Consul Template。NGINX Plus 支持更多的配置动态更新机制– 它可以使用DNS从服务注册中心拉取有关服务实例的信息,它也提供了API来远程完成配置重构。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐