关于Docker的服务发现与注册

来源:互联网 发布:淘宝1920全屏轮播代码 编辑:程序博客网 时间:2024/06/08 07:31


服务发现的背景

服务发现并不是新出现的概念,在分布式系统中是一个很基础的概念,并有很长的历史,DNS(域名系统)就是一个很好的例子。但是在最近一段时间,随着Docker和微服务架构的迅速发展,服务连接趋于动态化,服务的位置(IP和端口号)变化会非常频繁,动态服务注册和发现变得越来越重要,因此,越来越多的人开始关注服务发现。

服务发现的目的

在多台主机组成的集群中,通常情况下,通过用配置文件来让客户程序发现提供服务主机的IP地址和端口号。但是,在现代的基于云计算的微服务应用中,当部署更多的服务时,要解决这个问题变得非常复杂。在运行的系统中,由于人为的或自动的集群扩展、新的服务被部署以及主机宕机或被替换,服务的位置(IP和端口号)变化非常频繁。

服务发现的目的减少或消除组件之间的“手动”的连接。当你把你的应用程序推送进生产的时候,所有的这些事情都可以配置:数据库服务器的主机和端口,REST 服务的 URL 等等,在一个高可扩展的架构中,这些连接可以动态改变。一个新的后端可以被添加,一个数据库节点可以被停止。你的应用需要适应这种动态环境。

服务发现的定义

服务发现的基本思想[6]是任何一个应用的实例能够以编程的方式获取当前环境的细节。这是为了让新的实例可以嵌入到现有的应用环境而不需要人工干预。服务发现工具通常是用全局可访问的存储信息注册表来实现,它存储了当前正在运行的实例或者服务的信息。大多数情况下,为了使这个配置具有容错与扩展能力,这个工具分布式地存储在基础设施中的多个宿主机上。

服务发现是大多数分布式系统和面向服务的架构的重要组成部分,服务发现组件记录了(大规模)分布式系统中所有服务的信息,人们或者其它服务可以据此找到这些服务。复杂系统的服务发现组件要提供更多的功能,如存储元数据服务,健康监测,不同的查询功能,实时更新,等等。不同的使用情境,服务发现的含义也不同。例如,网络设备发现、零配置网络[12]、交汇发现和 SOA 发现等。无论是哪一种使用情境,服务发现提供了一种协调机制,方便服务的发布和查找。换一个方式来讲,服务发现就是利用服务发现工具来管理集群中的流程和服务找到它所涉及的相关服务并与之互相通信。它涉及到服务的目录,在该目录中注册服务,然后能够在该目录中查找并连接到服务。

服务发现工作在容器中

分布式服务发现系统的一个主要优势是它可以存储任何类型的组件运行时所需的配置信息。这就意味着可以从容器内将更多的配置信息抽取出去,并放入更大的运行环境中。每一个服务发现工具都会提供一套API,使得组件可以用其来设置或搜索数据[7]。正是如此,对于每一个组件,服务发现的地址要么硬编码到程序或容器内部,要么在运行时以参数形式提供。通常来说,发现服务用键值对形式实现,采用标准http协议交互。

服务发现的工作方式是:当每一个服务启动上线之后,他们通过发现工具来注册自身信息。它记录了一个相关组件若想使用某服务时的全部必要信息。例如,一个MySQL数据库服务会在这注册它运行的ip和端口,如有必要,登录时的用户名和密码也会留下。

当一个服务的消费者上线时,它能够在预设的终端查询该服务的相关信息。然后它就可以基于查到的信息与其需要的组件进行交互。负载均衡就是一个很好的例子,它可以通过查询服务发现门户得到各个后端节点承受的流量数,然后根据这个信息来调整配置。

这可将配置信息从容器内拿出。一个好处是可以让组件容器更加灵活,并不受限于特定的配置信息。另一个好处是使得组件与一个新的相关服务实例交互时变得简单,可以动态进行调整配置。

服务发现的特性

服务发现作为大规模服务定向的服务架构的支柱,服务发现需要高可用和三个关键的基础特性:注册,发现和查询。

服务发现支持大规模SOA核心服务,它必须是高可用的,如果其他的服务查询不到服务,那么整个系统是不可用的。根据CAP理论[11](一个分布式系统最多只能同时满足一致性、可用性和容错性着三项中的两项),如果需要分区容错(分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务),就需要协调一致性(更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致)和可用性(服务一直可用,而且是正常响应时间)的关系,因为网络分区总是会发生的,所以没有方法去跟分区容错协调,只能选择一致性和可用性与分区容错结合。一般情况下,可用性比较重要,但是当服务来自不同的存储的注册表的系统或数据库,在这种情况下,一致性相对来讲是比较重要的。所以在不同的使用环境里,服务发现的解决方案应该根据系统的基础设施特点进行选择。例如:基于什么样的平台,用的那种程序语言编写等。

服务发现另外一个关键性的能力就是元数据存储的能力。在大规模系统中,复杂的服务提供了多种服务接口和端口,部署环境也很复杂。因为一旦服务发现组件存储了大量的元数据,它就必须提强大的查询功能。同时包括健康和其他状态的查询。

负载均衡和监控也是很多服务发现系统提供的关键特性。服务发现监控服务实例的健康状态,保证服务的有效性和可用性。服务一般要实现心跳检测机制以保证服务的可用性,当注册服务失败了,可以利用服务发现方案立即移除失效的服务,并且客户端也需要能够可靠的处理服务失败的情况。

许多服务发现平台允许赋值时带一个可配置的超时时间。组件可以设置一个超时时间,并能定期去请求服务发现来重置超时时间。如果该组件出现故障,超时时间达到设定值,那么这个组件的连接信息就会从服务发现的存储中被去掉。超时时间长度在很大程度上是它与应用需要多快去应对一个组件的故障的函数。

这也可以通过将一个基本的容器与每一个组件相连来实现[9],而它们唯一的责任是定期的健康检查组件以及更新注册表如果组件关闭。这种类型的架构值得担忧是,如果辅助容器出现故障,将导致不正确的信息在存储中。一些系统解决这个问题的方法是在服务发现的工具中定义健康检查。这样,发现平台本身可以定期检查已注册组件是否仍然可用。

服务发现的优势

服务发现的主要好处是不用使用硬编码的网络地址[10],只需服务的名字(有时甚至连名字都不用)就能使用服务。在现代的体系架构中,单个服务实例的启动和销毁很常见,所以应该做到:无需了解整个架构的部署拓扑,就能找到这个实例。

 

服务注册的定义

服务发现的过程是指服务消费者向中央注册器查询服务的位置信息。服务注册的过程是将服务的位置注册到一个中央注册器中,通常会注册服务的IP和端口号,有时也会包括身份验证凭证、协议、版本号、环境等细节。服务注册中心是服务发现的关键部分,它是包含服务实例网络地址的数据库。服务注册中心需要高可用而且随时更新。客户端可以缓存从服务注册表获得的网络地址。然而,这些信息最终会变得过时,客户端也无法发现服务实例。因此,服务注册表由若干使用复制协议保持同步的服务器构成

服务实例在服务注册中心注册和解注册[2]。实现这两者有两种不同的方式。其一是自行注册模式。其二是第三方注册模式,即由其他系统逐渐管理服务的注册。

当我们使用自行注册模式时,一个服务实例负有将自己注册和解注册给服务注册中心的职责。并且,如果需要,服务实例需要发送心跳请求,以防止注册过期。

当使用第三方注册模式时,服务实例不用负责服务注册功能。取而代之的是,另一个可称为服务注册器的系统组件负责服务注册。服务注册器通过轮询或订阅事件的方式跟踪一组服务实例(状态)的改变。当服务注册器发现新的可用服务后,其将这个实例注册到服务注册中心。服务注册器也可以将销毁的实例解注册。这种模式的主要优点是将服务实例和服务注册中心解耦。你不需要为不同语言和框架实现服务注册逻辑。取而代之的是服务注册将通过一个专门的服务,按照一种集中化的方式进行。一个缺点是,除非部署环境内建支持,否则你需要另一个建立和管理另一个高可用的系统组件。

Netflix Eureka 是一个不错的服务注册中心例子。它提供了相关的 REST API。服务实例可以使用 POST 请求注册网络地址。每30秒必须通过 PUT 请求刷新注册。一个注册可以通过 HTTP DELETE 请求或超时被删除。客户端可以通过 GET 请求获取注册的服务实例。etcd[4]是一个高可用,分布式,一致性的键值存储,用来共享配置和服务发现。KubernetesCloud Foundry都使用etcdConsul[8]一个服务发现和配置的服务。它提供API使得客户端可以注册和发现服务。Consul 可以执行健康检查已决定服务是否可用。Apache Zookeeper被广泛使用的,高性能的,用于协调分布式应用的服务。最初,Zookeeper 是 Hadoop 的子项目,但现在是Apache的顶级项目。

在一些部署环境中,我们需要通过使用例如 Netflix Eureka、etcd 或 Zookeeper建立我们自己的服务发现基础架构。在另一些环境中,服务发现机制是内建的,例如 Kubernetes是和Marathon处理服务注册和解注册。它们同样在每个集群宿主机上运行代理,起到服务端发现模式中路由器的作用。

服务发现工具分析

目前,业界提供了很多种服务发现解决方案。如何判断那种服务发现的解决方案最可靠,首先服务发现解决方案应该具备三个方面[1]:第一,具有一致性,高可用的工作目录;第二,具备注册服务和监管服务健康的机制;第三,具备查询并连接到服务的机制。

下面对业界比较常见的服务发现解决方案进行简单的介绍。
ZooKeeper是最成熟的配置存储方案,它的历史比较长,它起源于Hadoop,帮助在Hadoop集群中维护各种组件。它非常成熟、可靠,被许多大公司(YouTube、eBay、雅虎等)使用。其数据存储的格式类似于文件系统,如果运行在一个服务器集群中,Zookeper将跨所有节点共享配置状态,每个集群选举一个领袖,客户端可以连接到任何一台服务器获取数据。提供了包括配置管理、领导人选举和分布式锁在内的完整解决方案。因此,ZooKeeper是非常有竞争力的通用的服务发现解决方案当然,它采用Java开发以及相当数量的依赖,因此也显得过于复杂。etcd 和 doozerd 是新近出现的服务发现解决方案,etcd面向容器和宿主机提供服务发现和全局配置存储功能。它们与 ZooKeeper 具有相似的架构和功能,因此可与 ZooKeeper 互换使用。
Consul是一种更新的服务发现解决方案[3]。除了服务发现,它还提供了配置管理和一种键/存储。Consul提供了服务节点的健康检查功能,Consul提供了一个内置的服务发现的框架。客户只需要注册服务并通过DNS或HTTP接口执行服务发现。 Consul 与 ZooKeeper 的主要区别是:Consul提供了DNS和HTTP 两种 API,而Zookeeper和etcd只提供原始的键/值队存储,要求应用程序开发人员构建他们自己的系统提供服务发现功能。

 

 

参考文献:

[1].http://progrium.com/blog/2014/07/29/understanding-modern-service-discovery-with-docker/

[2].https://www.nginx.com/blog/service-discovery-in-a-microservices-architecture/

[3].http://jasonwilder.com/blog/2014/02/04/service-discovery-in-the-cloud/

[4].https://segmentfault.com/a/1190000000730186#articleHeader1

[5].http://jasonwilder.com/blog/2014/07/15/docker-service-discovery/

[6].http://dockone.io/article/667

[7].http://dockone.io/article/259

[8].https://www.consul.io/

[9].https://www.digitalocean.com/community/tutorials/the-docker-ecosystem-service-discovery-and-distributed-configuration-stores

[10].https://highops.com/insights/service-discovery-6-questions-to-4-experts/

[11].https://zh.wikipedia.org/wiki/CAP%E5%AE%9A%E7%90%86

[12]..赵昕,郭恩全,李小杰,胡华伟.一种实现网络自动配置及服务发现的零配置协议[J].计算机测量与控制,2008,08:1190-1191.

[13].段丽君.服务发现中的用户偏好模型构建方法分析与比较[J].湖北第二师范学院学报,2016,02:61-64.