4.服务发现@微服务的设计与实现

4. 微服务发现

这是这本书的第 4 章,它是关于用微服务构建应用的。第一章介绍了微服务架构模式,并讨论了使用微服务的优点和缺点。第 2 章和第 3 章描述了微服务之间通信的各种不同机制。 在本章中,我们将详细探索微服务发现的相关问题。

为什么使用服务发现?

让我们假设你在编写一段代码调用一个有 REST API 或者 Thrift API 的服务。为了发送一个请求,你的代码需要知道一个服务实例的网络位置(IP地址和端口)。在一台物理机器上运行的一台传统应用程序,服务实例的网络位置是相对静态的。比如,你的代码可以从一个配置文件中读取网络的位置,这个文件会偶尔更新。

在现代,基于云的微服务应用程序,然而,解决这个问题要困难得多,如图4-1所示。

服务实例动态地分配网络位置,此外,由于自动伸缩(autoscaling), failures(失效),和升级(upgrades)。会动态的更改服务实例。因此,你的客户端代码需要使用一个更加精心制作的服务发现机制。

在这里插入图片描述

这儿有两种主要类型的服务发现模式: 客户端侧发现模式(client-side discovery)和服务侧的发现模式(server-side discovery)。让我们先看一下客户端侧的发现模式。

客户端侧发现模式(The Client-Side Discovery Pattern)

当使用客户端侧发现模式(client-side discovery pattern), 客户端负责确定可用服务实例的网络位置,并在整个实例中加载平衡请求。client查询服务注册表。它是可用服务实例的数据库。然后,客户机使用负载平衡算法选择一个可用的服务实例并发出请求。
图 4-2 显示了这种模式的架构:

在这里插入图片描述

服务实例的网络位置在它启动时注册到服务注册中心。当实例中断的时候,将从服务这次表中移除。服务实例的注册通常通过一种心跳机制周期性地刷新。

Netflix OSS 提供了客户端发现模式的一个很好的例子。它提供了一个REST API来管理服务实例注册和查询可用实例。Netfix Ribbon 是一个跨进程客户端,和 Eureka 一起工作,用于在可用的服务实例中间负载君合请求。在这章的后面我们将更加深入地讨论一下Eureka。

客户端侧发现模式(the client-side discovery)有各种各样的优点和缺点。这个模式相对简单,而且除了服务注册中心之外,没有其他可移动的部分。同样的,因为客户端知道可用的服务实例。它可以做出智能的、特定于应用程序的负载平衡决策,例如一致地使用散列(hashing consistently)。
这个模式的一个明显的缺点是,它将client与服务注册中心耦合在一起。你必须为每种编程语言和你的服务客户端使用的框架实现客户端侧的服务发现。

现在我们已经了解了客户端侧的服务发现(client-side discovery), 让我们看一下服务侧的发现(server-side discovery)。

服务端侧的发现模式(The Server-Side Discovery Pattern)

另外一种服务发现的方式是服务侧的发现模式(server-side discovery pattern)。图4-3显示了这种模式的结构:

在这里插入图片描述

客户(client) 发送一个请求(request)经过负载均衡器(load balancer)。负载均衡器查询服务注册表(service registry)并将每个请求路由到一个可用的服务实例。和客户侧发现一样,服务实例也是用服务注册进行注册和注销的。

AWS 弹性负载均衡器(ELB:AWS Elastic Load Balancer)是一个服务侧发现路由(server-side discovery router)的例子。ELB 通常用于加载来自 Internet 的外部流量的负载均衡。然而,你也可以使用ELB对VPC内部的流量进行负载均衡。一个客户端(client)使用其DNS name通过ELB发出请求(HTTP或TCP)。ELB负载在一组注册的弹性计算云(EC2)实例之间 或EC2 Container Service (ECS)容器之间平衡流量。没有单独可见的服务注册中心。相反,EC2实例和ECS容器是在ELB本身注册的。

HTTP服务器和负载均衡器,如NGINX Plus和NGINX也可以用作服务器端发现负载均衡器。例如,这篇博客描述了使用 Consul Template 来动态地重新配置 NGINX 反向代理。Consul Template,Consul Template是从Consul服务注册中心中存储的配置数据定期重新生成任意配置文件的工具。每当文件更改时,它就运行一个任意的shell命令。在博文中描述的示例中,Consul Template生成了一个NGINX .conf文件,该文件配置反向代理,然后运行一个命令,告诉NGINX重新加载配置。一个更加复杂的实现可能会使用他的 HTTP 或者 DNS 动态地重新配置 NGINX。

一些部署环境,例如 Kubernetes 和 Marathon, 在这个集群中的每个主机上运行一个代理。这个代理从当了服务侧发现复杂均衡的角色。为了向服务发出请求,客户端使用主机的IP地址和服务分配的端口通过代理路由请求。然后,代理透明地将请求转发到集群中某处运行的可用服务实例.

服务侧的发现模式有一些优点和缺点。这个模式最大的优点是发现的细节从client段抽象出来了。client简单的发送请求到负载均衡器。这样就不需要为服务客户机使用的每种编程语言和框架实现发现逻辑。同样,就像前面提到的,一些部署环境免费提供了这个功能。这个模式也有一些缺点,然而,除非部署环境提供了负载均衡器。它是您需要设置和管理的另一个高可用性系统组件。

服务注册中心(The Service Registry)

服务注册中心是服务发现的一个关键部分。他是一个包含了服务实例网络位置的数据库。服务注册中需要高可用和实时的。客户端可以缓存从服务注册中心获取到的网络位置。然而,哪些信息最终变成过时的,客户端无法发现服务实例。因此,一个服务注册中心包含一个集群的服务,并使用应答协议来维持一致性。

就像之前提到的,Netflix Eureka 是一个服务注册的好例子。它提供了一个 REST API用来注册和查询服务的实例。一个服务实例使用一个POST请求注册它的网络位置。每隔30秒他必须使用一个 PUT 请求刷新它的位置。通过使用HTTP删除请求或实例注册超时来删除注册。就像你可能期待的那样,客户端(client)能够通过使用一个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,这个API允许 clients 注册和发现服务。Consul 可以进行心跳检查,以确定服务的可用性。
  • Apache ZooKeeper, 广泛使用的、高性能的分布式应用协调服务。Apache ZooKeeper最初是Hadoop的子项目,但现在是一个独立的顶层项目。

同样,就像之前提到的,一些系统,比如 Kubernetes, Marathon, 和 AWS, 并没有一个显式的服务注册中心。相反,服务注册中心只是基础设施的内置部分。

既然我们已经了解了服务注册中心的概念,现在让我们看看如何向服务注册中心注册服务实例。

服务注册选项(Service Registration Options)

就像之前提到的,服务实例必须在服务注册表中注册和注销。有几种不同的方法来处理注册和注销。一种选择是让服务实例注册自己, 自己注册的模式。 另一个其他选项是用一些其他系统组件来服务实例的注册。第三方注册模式, 让我们先看一下自我注册模式。

自我注册模式(The Self-Registration Pattern)

当使用自我注册模式(self-registration pattern),一个服务实例自己负责在服务注册表注册和注销。同样的,如果需要的话,服务实例发送心跳请求以防止注册过期。

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

在这里插入图片描述

这种方法的一个好的例子是 Netflix OSS Eureka client。 Eureka client 处理服务实例注册和注销的所有方面。Spring Cloud 工程。 它实现了各种模式,包括服务发现, 使自动向Eureka注册服务实例变得容易。你简单的用 @EnableEurekaClient 注解来注解你的Java配置类。

自我注册模式有各种优点和缺点。一个优点是它相对检点,并不需要任何其他系统组件。然而,最大的缺点是,它将服务实例和服务注册中心耦合在一起了。你必须实现你服务中用到的各种编程语言和框架的注册代码。

另外一个方法,将服务和注册中心解耦了,就是第三方注册模式。

第三方注册模式(The Third-Party Registration Pattern)

当使用第三方注册模式,服务实例本身并不复杂将他们注册到服务注册中心。取而代之的是,另一个称之为服务注册(service registrar)的系统组件,服务注册通过轮询部署环境或订阅事件来跟踪对运行实例集的更改。当它注意到一个新可用的服务实例时,它将该实例注册到服务注册中心。服务注册中心还注销已终止的服务实例。

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

在这里插入图片描述

service registrar 的一个例子是开源的工程 Registrator。它会自动注册和注销部署为Docker容器的服务实例。注册器支持多种服务注册中心,包括etcd和Consul。

另外一个 service registrar 的例子是 NetflixOSS Prana。它主要用于使用非jvm语言编写的服务,是一个与服务实例一同并行运行的应用程序。Prana向Netflix Eureka注册和注销服务实例。

服务注册器子某些部署环境中是一个内置的组件。由自动缩放组创建的EC2实例可以自动注册到ELB, Kubernetes服务会自动注册并供发现使用。

第三方注册模式有各种优点和缺点。一个主要的优点是服务和服务注册中心解耦了。你不需要为你的程序员使用的各种编程语言和框架实现服务注册逻辑。取而代之的是,服务实例注册是在专用服务中集中处理的。

这种模式的一个缺点是,除非将其内置到部署环境中,否则它仍然是另一个需要设置和管理的高可用性系统组件。

总结

在一个微服务应用程序中,正在运行的服务实例集会动态更改。实例已经动态地制定了网络位置。因此,client为了要向服务发出请求,它必须使用服务发现机制。

服务发现的一个关键部分是服务注册中心。服务注册中心是一个包含所有可用服务实例的数据库。服务注册中心提供了一个管理API和查询API。服务实例通过使用管理API, 在服务注册中心注册或注销服务。系统组件使用查询API开发现可用的服务实例。

有两种主要的服务发现模式:客户侧发现和服务侧发现。在使用客户侧发现的系统中,客户查询服务注册中心,选择一个可用的实例,并发送请求。在使用服务侧发现的系统中,客户侧通过 router 发送请求,router 查询服务注册中心,然后将请求路由到一个可用的实例。

服务实例有两种主要的方法从服务注册表中注册和注销。其中一个选项是服务实例自己到服务注册中心注册,就是自我注册模式。另外一个选项是用其他系统组件代替服务完成服务注册中心的注册和注销行为,这就是第三方注册模式

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

一个 HTTP 反向代理和负载均衡器,比如NGINX, 也可以用作服务侧发现的负载均衡器。服务注册中心可以将路由信息推送到NGINX,并调用一个优雅的配置更新;例如,您可以使用Consul Template。NGINX Plus支持额外的动态重新配置机制——它可以使用DNS从注册表中获取服务实例的信息,并且它提供了一个用于远程重新配置的API。

Microservices in Action: NGINX Flexibility

在微服务环境下,由于自动伸缩、故障和升级,您的后端基础设施可能会随着服务的创建、部署和伸缩而不断变化。如本章所述,在需要动态重新分配服务位置的环境中需要服务发现机制。

在微服务中使用NGINX的部分好处是,你可以很容易地配置它来自动响应后端基础设施的变化。NGINX的配置不仅简单灵活,它还与模板的使用兼容,就像在Amazon Web Services中使用的那样,使得管理特定服务的更改和管理受负载均衡影响的服务集更容易。NGINX Plus提供了一个动态的重新配置API,无需重新启动NGINX Plus或手动重新加载配置以使其识别正在进行负载均衡的服务集群的变化。 在 NGINX Plus Release 8 后之后的版本中,您可以将API所做的更改配置为在重启和重新加载配置时保持不变。(重新加载不需要重新启动,也不丢弃连接。)。NGINX Plus Release 9及其后续版本支持使用DNS SRV记录进行服务发现,可以与现有的服务器发现平台(如Consul和etcd)紧密集成。

我们在NGINX创建了一个管理服务发现的模型:

  1. 为每一个应用运行单独的Docker容器,包括一个服务发现应用(如etcd),一个服务注册工具,一个或多个后端服务器,以及NGINX Plus本身来负载平衡其他容器。
  2. 注册工具监视Docker是否有新的容器,并使用服务发现工具注册新的服务,同时删除消失的容器。
  3. 容器及其运行的服务将自动添加到或从负载平衡的上游服务器组中删除。

这个过程的演示应用程序可用于几个服务发现应用程序:Consul APIs, DNS SRV records from Consul, etcd,和ZooKeeper

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值