Consul是一个免费的开源工具,它提供了服务发现、健康检查、负载均衡和全局分布式的键值存储。此外,它还提供了一组用于构建编排工作流和工具的原型。在微服务体系架构中,应用程序通常运行在许多IP地址上,并绑定到各种端口。服务发现有助于发现这些不同的服务,而不管它们位于何处。
由于同一服务的多个实例常常在微服务体系架构中同时运行,因此我们需要一种策略,以便在处理健康状态的更改、实例数量的更改和集群状态的更改时,均衡地平衡服务的所有健康实例的流量。这是负载均衡层的工作。本文讨论了在微服务体系架构中与Consul负载均衡的一些常见策略。
与Consul负载均衡的一种方法是使用Consul的内置负载均衡功能。Consul集成健康检查与服务发现。这意味着不健康的主机永远不会从查询返回到服务发现层。在这种模式下,每当应用程序和服务希望在数据中心中找到其他服务时,它们都直接与Consul进行通信。
请考虑以下配置文件,其中包含后端服务的IP地址:
services:
backend: 10.2.5.391
通常认为硬编码IP地址是一种不好的做法,尤其是在微服务体系结构中。随着应用程序在整个系统中移动,使这个配置文件保持最新变得很有挑战性,特别是在计算机集群中。相反,更好的方法是利用Consul的DNS发现层。
services:
backend: backend.service.consul
正如“www.hashicorp.com”是一个web地址,“backend.service.consul”也是一样。TLD或域后缀是可配置的,但默认值是.consul。以TLD结尾的任何请求都将被解析到Consul。.service命名空间告诉Consul查找服务(与机器节点相对照)。backend 是要查找的服务的名称。请求“backend.service.consul"解析到一组IP地址,就像请求“www.hashicorp.com”解析到一组IP地址一样。然而,对于Consul,解析发生在服务发现层,并集成到健康检查机制中。
每当应用程序或内核解析这个DNS条目时,它将收到一组IP地址的随机round-robin响应,这些地址对应于集群中的健康服务。DNS接口基本上提供了与任何应用程序的零接触服务发现集成。
Fabio是一个开源工具,它为Consul管理的服务提供了快速、现代、零配置负载均衡HTTP(S)和TCP路由器。用户注册服务和健康检查到Consul,fabio将自动路由流量到他们,不需要额外的配置。
用户注册一个以urlprefix-开头的标签的服务,例如:
urlprefix-/my-service
在本例中,当对fabio 发出/my-service请求时,fabio将自动将流量路由到集群中的健康服务。Fabio还支持更高级的路由配置。
Consul负载均衡的另一种方法是使用第三方工具(如Nginx或HAProxy)来平衡流量,以及使用开源工具(如 Consul Template)来管理配置。在这种模式下, Consul Template动态地管理nginx.conf或haproxy.conf配置文件,它定义负载均衡器和服务器列表。这个列表是模板化的,Consul Template作为一个服务运行,以保持模板是最新的。Consul Template与Consul集群有持续的连接,当发生对服务池的更改时, Consul Template写入一个新的配置文件,并向Nginx或HAProxy进程发送信号,以重新加载其配置。下面是一个示例Nginx Consul Template模板:
upstream myapp {
{{ range service "myapp" }}
server {{ .Address }}:{{ .Port }}
{{ end }}
}
在本例中,Consul Template将监视所有名为“myapp”的服务。如果他们的状态发生了更改,Consul Template将渲染一个新的配置文件,并向Nginx进程发出重新加载的信号。上面的模板将渲染nginx.conf成下面这样:
upstream myapp {
server 10.2.5.60:13845
server 10.6.96.234:45033
server 10.10.20.123:18677
}
需要注意的是,在这种模式下,无论是Nginx还是HAProxy都不知道Consul的存在;它们只是读取配置,就好像值是由操作符或配置管理工具硬编码的一样。
最近,我制定了一个目标,试图从等式中删除 Consul Template,但要保持Nginx经过时间考验的灵活性和熟悉性。社区内有一些非常有趣和创新的方法,即:
最终,这些方法要么涉及太多的活动部件,要么包含超出Consul公司基本服务发现范围的特性。因此,我编写了ngx_http_consul_backend_module模块,该模块对每个nginx请求动态地选择上游。
就像这样:
http {
server {
listen 80;
server_name example.com;
location /my-service {
consul $backend service-name;
proxy_pass http://$backend;
}
}
}
对于每个请求,Consul密钥告诉Nginx将委托给自定义模块并选择一个随机的健康后端,然后将请求代理给该后端。确实有需要改进的地方,但是这种概念验证表明,在没有中介工具的情况下,Nginx和Consul可以直接连接在一起。
HAProxy 1.8(目前是本文撰写时的发布候选版本)添加了内置功能,无需使用第三方工具或模块,即可通过DNS找到服务。HAProxy已经有内置DNS解析器一段时间了,但是HAProxy 1.8通过SRV记录和EDNS的支持为端口带来了解析,使其与Consul完美地匹配。
Consul负载均衡的微服务应用有很多策略和技术。这篇文章详细介绍了一些最常见的技术,并希望能够激发灵感,找到新的和令人兴奋的方法来集成行业标准负载平衡工具和Consul。无论您是直接使用Consul,桥接与Consul Template的差距,编译自定义的Nginx自己,或尝试HAProxy 1.8发布候选,我们期待听到您如何平衡您的微服务负载。