我们拥有的服务越多,如果我们使用预定义的端口,就会发生冲突的可能性越大。毕竟,在同一端口上不能监听两个服务。管理一百个服务所使用的所有端口的紧密列表本身就是一项挑战。将那些服务所需的数据库添加到该列表中,数量会增长得更多。出于这个原因,我们应该在不指定端口的情况下部署服务,并让Docker为我们分配一个随机服务。唯一的问题是我们需要发现端口号并让其他人了解它。
当我们开始使用部署到多个服务器之一的服务的分布式系统时,事情变得更加复杂。我们可以选择事先定义哪个服务转到哪个服务器但会导致很多问题。我们应该尽可能地利用服务器资源,如果我们事先定义在哪里部署每个服务,这几乎是不可能的。另一个问题是服务的自动扩展最多是困难的,更不用说服务器故障的自动恢复。另一方面,如果我们将服务部署到服务器(例如,运行的容器数量最少),我们需要将IP添加到需要在某处发现和存储的数据列表中。
当我们需要存储和检索(发现)与我们正在使用的服务相关的一些信息时,还有许多其他案例。
为了能够找到我们的服务,我们至少需要以下两个流程供我们使用。
- 服务注册过程,至少将存储正在运行的主机和端口服务。
- 服务发现过程,允许其他人能够发现我们在注册过程中存储的信息。
除了这些过程,我们还需要考虑其他几个方面。如果服务停止工作并部署/注册新实例,我们是否应取消注册该服务?当有多个同一服务的副本时会发生什么?我们如何平衡它们之间的负载?如果服务器出现故障会怎样?这些和许多其他问题与注册和发现过程密切相关。目前,我们仅将范围限制为服务发现(包含上述两个流程的通用名称)以及我们可能用于此类任务的工具。其中大多数都具有某种高可用性的分布式键/值存储。
服务发现工具
服务发现工具的主要目标是帮助服务找到并相互通信。为了履行职责,他们需要知道每项服务的位置。这个概念并不新鲜,很多工具早在Docker诞生之前就存在了。但是,容器使这种工具的需求达到了一个全新的水平。
服务发现背后的基本思想是服务(或应用程序)的每个新实例能够识别其当前环境并存储该信息。存储本身通常以密钥/值格式在注册表中执行。由于该发现通常用于分布式系统,因此注册表需要是可伸缩的,容错的并且在集群中的所有节点之间分布。这种存储的主要用途是至少向可能需要与之通信的所有相关方提供服务的IP和端口。这些数据通常会与其他类型的信息一起扩展。
发现工具倾向于提供某种API,服务可以使用它来注册自己以及其他人查找有关该服务的信息。
假设我们有两项服务。一个是提供者,另一个是消费者。部署提供程序后,我们需要将其信息存储到所选的服务发现注册表中。稍后,当消费者尝试访问提供者时,它将首先查询注册表并使用从注册表获得的IP和端口调用提供者。为了将提供者与注册表的特定实现分离,我们经常使用某种代理服务。这样,消费者将始终从驻留在代理内的固定地址请求信息,而该代理又将使用发现服务来找出提供者信息并重定向请求。我们将通过反向代理后来在书中。现在,了解基于三个参与者的流程非常重要; 消费者,代理和提供者。
我们在服务发现工具中寻找的是数据。至少我们应该能够找到服务的位置,服务是否健康以及服务的配置。由于我们正在构建具有多个服务器的分布式系统,因此该工具需要健壮,并且一个节点的故障不应该危及数据。此外,每个节点应具有完全相同的数据副本。此外,我们希望能够以任何顺序启动服务,能够销毁它们或用更新的版本替换它们。我们还应该能够重新配置我们的服务并相应地查看数据变化。
让我们看看几个常用的选项来完成我们设定的目标。
手动配置
大多数服务仍然是手动管理的。我们事先决定在哪里部署服务,它的配置是什么,并希望它能够继续正常工作直到结束。这种方法不易扩展。部署服务的第二个实例意味着我们需要全面启动手动过程。我们需要启动一个新服务器或找出哪个资源利用率低,创建一组新配置并进行部署。在硬件故障的情况下情况更加复杂,因为当手动管理事物时,反应时间通常很慢。可见性是另一个痛苦的观点。我们知道静态配置是什么。毕竟,我们提前准备好了。但是,大多数服务都有大量动态生成的信息。这些信息不容易看到。当我们需要这些数据时,我们无法查询单一位置。
由于大量手动操作的移动部件,反应时间不可避免地缓慢,故障恢复能力最多可疑并且监控难以管理。
虽然在过去或者服务和/或服务器数量较少的情况下手动完成这项工作是有借口的,但随着服务发现工具的出现,这种借口很快就会消失。
zookeeper,简称zk, 动物园管理员
ZooKeeper是此类型中最古老的项目之一。它起源于Hadoop世界,它是为了帮助维护Hadoop集群中的各种组件而构建的。它成熟,可靠,并被许多大公司(YouTube,eBay,雅虎等)使用。它存储的数据格式类似于文件系统的组织。如果在服务器群集上运行,Zookeper将在所有节点之间共享配置状态。每个集群选择一个领导者,客户端可以连接到任何服务器以检索数据。
Zookeeper带来的主要优势是成熟度,稳健性和功能丰富性。然而,它也有其自身的一些缺点,Java和复杂性是主要的罪魁祸首。虽然Java对于许多用例来说都很棒,但对于这类工作来说却非常繁重。Zookeeper对Java的使用以及相当多的依赖性使得它在竞争中更加资源匮乏。除了这些问题,Zookeeper也很复杂。维护它需要比我们从这种类型的应用所期望的更多的知识。这是功能丰富性将自身从优势转化为负债的部分。应用程序具有的功能越多,我们不需要所有功能的机会就越大。因此,我们最终会以复杂的形式为我们并不完全需要的东西付出代价。
Zookeeper铺平了其他人的方式,并取得了相当大的进步。“大玩家”正在使用它,因为当时没有更好的选择。今天,Zookeeper显示了它的年龄,我们的选择更好。
ETCD
etcd是可通过HTTP访问的键/值存储。它是分布式的,具有可用于构建服务发现的分层配置系统。它易于部署,设置和使用,提供可靠的数据持久性,安全性和非常好的文档。
由于其简单性,etcd是比Zookeeper更好的选择。但是,它需要与少数第三方工具结合才能提供服务发现目标。
现在我们有了一个存储与我们服务相关的信息的地方,我们需要一个能够自动将该信息发送给etcd的工具。毕竟,如果可以自动完成,我们为什么要手动将数据输入到etcd。即使我们想要将信息手动输入到etcd,我们通常也不知道该信息是什么。请记住,服务可能部署到运行最少容器的服务器,并且可能已分配随机端口。理想情况下,该工具应监视所有节点上的Docker,并在运行新容器或停止现有容器时更新etcd。可以帮助我们实现这一目标的工具之一是Registrator。
Registrator
Registrator通过检查容器在线或停止时自动注册和取消注册服务。它目前支持etcd,Consul和SkyDNS 2。
Registrator结合etcd是一个强大而简单的组合,它允许我们练习许多高级技术。每当我们调出容器时,所有数据都将存储在etcd中并传播到集群中的所有节点。我们对这些信息的处理取决于我们。
还有一块拼图丢失了。我们需要一种方法来创建配置文件,其中包含存储在etcd中的数据,以及在创建这些文件时运行一些命令。
confd
confd是一个轻量级的配置管理工具。常见用法是使用存储在etcd,consul和少数其他数据注册表中的数据使配置文件保持最新。它还可用于在配置文件更改时重新加载应用程序。换句话说,我们可以将它用作使用etcd(或许多其他注册表)中存储的信息重新配置所有服务的方法。
关于etcd,Registrator和confd组合的最终想法
当etcd,Registrator和confd相结合时,我们会得到一种简单而强大的方法来自动化我们所有的服务发现和配置需求。这种组合还证明了正确组合“小”工具的有效性。这三个人正是我们需要他们做的事情。不到这一点,我们就无法实现摆在我们面前的目标。另一方面,如果它们的设计考虑到更大的范围,我们会在服务器资源上引入不必要的复杂性和开销。
在我们做出最终判决之前,让我们看一下具有类似目标的另一种工具组合。毕竟,我们不应该在没有调查替代方案的情况下解决某些问题。
Consul
Consul是一个强大的一致数据存储区,它使用八卦来形成动态集群。它具有分层键/值存储,不仅可用于存储数据,还可用于注册可用于各种任务的监视,从发送有关数据更改的通知到运行运行状况检查和自定义命令(取决于其输出)。
与Zookeeper和etcd不同,Consul实现嵌入式服务发现系统,因此无需构建自己的服务或使用第三方服务。此发现包括对其上运行的节点和服务的运行状况检查。
ZooKeeper和etcd仅提供原始的K / V存储,并要求应用程序开发人员构建自己的系统以提供服务发现。另一方面,Consul为服务发现提供了内置框架。客户端只需要使用DNS或HTTP接口注册服务并执行发现。其他两个工具需要手工解决方案或使用第三方工具。
Consul为多个数据中心和八卦系统提供开箱即用的本机支持,这些系统不仅适用于同一集群中的节点,也适用于数据中心。
Consul有另一个很好的功能,可以区别于其他功能。它不仅可用于发现有关已部署服务及其所在节点的信息,还可通过HTTP请求,TTL(生存时间)和自定义命令轻松扩展运行状况检查。
Registrator
Registrator有两个Consul协议。所述consulkv协议产生类似的结果作为与该ETCD协议获得的那些。
除了通常与etcd或consulkv协议一起存储的IP和端口之外,Registrator的consul协议还存储了更多信息。我们获取有关运行服务的节点的信息以及服务ID和名称。除了少量额外的环境变量,我们还可以以标签的形式存储其他信息
consul模板
confd可以与consul一样使用,与etcd一样。然而,Consul拥有自己的模板服务,其功能更符合Consul提供的服务。
该模板是建立与confd获得的值文件非常方便的方式。作为额外的奖励,它还可以在文件更新后运行任意命令。就像confd一样,consul-template也使用Go Template格式。
consul健康检查,Web UI和数据中心
监视群集节点和服务的运行状况与测试和部署本身一样重要。虽然我们应该致力于拥有永不失败的稳定环境,但我们也应该承认意外的失败发生并准备采取相应的行动。例如,我们可以监视内存使用情况,如果达到某个阈值,则将某些服务移动到集群中的其他节点。这将是在“灾难”发生之前执行的预防措施的一个例子。另一方面,并非所有潜在的故障都能及时检测到我们按时采取行动。单个服务可能会失败。由于硬件故障,整个节点可能会停止工作。在这种情况下,我们应该准备尽可能快地采取行动,例如,用新的节点替换节点并移动失败的服务。领事有一个简单,优雅,
如果您搜索“etcd ui”或“etcd仪表板”,您可能会看到有一些可用的解决方案,可能会问我们为什么没有提供它们。原因很简单; etcd是一个键/值存储,而不是更多。拥有用于呈现数据的UI并没有多大用处,因为我们可以通过etcdctl轻松获取它。这并不意味着etcd UI没有用,但由于其范围有限,它没有太大的区别。
Consul不仅仅是一个简单的键/值存储。正如我们已经看到的,除了存储简单的键/值对之外,它还具有服务概念以及属于它的数据。它还可以执行运行状况检查,从而成为仪表板的良好候选者,可用于查看在其上运行的节点和服务的状态。最后,它理解多个数据中心的概念。所有这些功能相结合,让我们看到了对不同灯光仪表板的需求。
使用Consul Web UI,我们可以查看所有服务和节点,监控运行状况检查及其状态,读取和设置键/值数据以及从一个数据中心切换到另一个数据中心。
关于Consul,Registrator,Template,健康检查和Web UI的最终想法
在许多情况下,Consul与我们探索的工具一起比etcd提供的解决方案更好。它的设计考虑了服务架构和发现。它很简单,但功能强大。它提供了一个完整的解决方案,而且不会牺牲简单性,在许多情况下,它是服务发现和健康检查需求的最佳工具。
结论
所有工具都基于类似的原则和架构。它们在节点上运行,需要仲裁才能运行并且非常一致。它们都提供某种形式的键/值存储。
zk是三个中最老的,年龄表现在其复杂性,资源利用和目标。它的设计时间与我们评估的其他工具的年龄不同(即使它不是很老)。
ETCD与Registrator和confd是可以解决大部分,如果不是所有的我们的服务发现的需求,一个非常简单但非常强大的组合。它还展示了我们在结合简单和非常具体的工具时可以获得的强大功能。它们中的每一个都执行一项非常具体的任务,通过完善的API进行通信,并且能够使用相对自治。他们自己在建筑和功能方面都是微服务。
Consul的不同之处在于,无需使用第三方工具即可支持多个数据中心和健康检查。这并不意味着使用第三方工具很糟糕。实际上,在整个博客中,我们尝试通过选择性能优于其他工具而不引入不必要的功能开销来组合不同的工具。当我们使用正确的工具完成工作时,可以获得最佳结果。如果该工具的功能超过我们所需的工作,其效率就会下降。另一方面,不做我们需要它的工具是没用的。领事达到了正确的平衡。它做的事情很少,而且做得很好。
Consul使用八卦传播集群知识的方式使得设置比etcd更容易,尤其是在大数据中心的情况下。将数据存储为服务的能力使得它比etcd中的键/值存储更加完整和有用(尽管Consul也有这个选项)。虽然我们可以通过在etcd中插入多个密钥来完成相同的操作,但Consul的服务可以实现更紧凑的结果,通常需要单个查询来检索与服务相关的所有数据。最重要的是,Registrator具有相当好的领事协议实现,使得两者成为一个很好的组合,特别是当consul-template被添加到这张图片时。Consul的Web UI就像一块蛋糕上的樱桃,提供了一种可视化服务和健康的好方法。
我不能说领事是一个明显的赢家。相反,与etcd相比,它略有优势。作为一个概念的服务发现以及我们可以使用的工具是如此新颖,以至于我们可以期待这个领域的很多变化。要有一个开放的心态,并试着从这篇文章中汲取一些建议。尝试不同的工具并做出自己的结论。
作者:sunsky303