Spring Cloud微服务运维神器之Consul Template?

1,645 阅读7分钟

Spring Cloud微服务架构浅析

这篇文章中要和大家分享下的就是在Spring Cloud微服务架构模式中被运维小哥用的很爽的一个工具Consul Template?

在具体介绍Consul Template是个什么东西之前,我们先来整体看一张微服务模式下的系统架构图,如下图所示:

在上图中,我们看到在基于Spring Cloud的微服务体系中,所有的微服务都会被注册到统一服务注册中心进行服务管理,这里使用的服务注册中心是Consul。假设在正常情况下,我们面向C端用户设计了一套微服务逻辑,用户端App通过域名访问后端微服务逻辑,而访问的调用链路是通过将公网域名透过DNS解析到我们的Nginx反向代理服务器,而Nginx服务器则需要将请求打到我们的Api Gateway微服务网关(如Zuul或Spring Cloud Gateway)上。之后,Api Gateway就会根据客户端访问的具体服务路径,将请求透过Consul的服务发现转发到具体的微服务中,例如访问订单微服务相关的接口Api Gateway就会将请求打到订单微服务中。

而我们知道在Spring Cloud微服务系统中,虽然Api Gateway网关服务本身并没有什么业务逻辑,除了进行服务路由外,也就只是通过编写过滤器实现一些常见的服务鉴权之类的逻辑,但其本身与其他微服务一样都是被注册中心管理的,而在容器化的时代Api Gateway与其他微服务一样也可能是被部署在Docker容器中,其IP端口地址本身并不是固定的。所以如果我们之前了解过Nginx反向代理配置的话,此时心里就会有疑问,Api Gateway服务的IP端口都不固定怎么搞反向负载均衡配置呢?

是不是我们应该要将Api Gateway特殊处理下,把Api Gateway的部署采用固定主机IP+端口的部署方式进行运维呢?答案显然是可以的,但是问题是这样做本身是不是就额外增加了微服务架构的复杂度?同时也降低了了Api Gateway网关服务部署的灵活性呢?所以,这个时候Consul Template就横空出世了!

Consul Template是做什么的?

说了这么多,那么Consul Template到底是做什么的呢?根据官方说明Consul Template比较关键的一个使用场景就是可以帮助我们获取Consul集群中服务的列表以及服务的所有服务地址和端口。可能有同学会问,这不就是Consul本身支持的功能吗?的确,没啥毛病,Consul Template本身就是一个工具,其关键之处在于它通过这种方式可以很方便地与Nginx代理服务器集成。从而可以帮助Nginx动态地根据Consul中的服务信息维护自身的服务列表,从而与整个Spring Cloud微服务体系形成联动,实现端到端的高可用架构体系。

此外,通过Consul Template我们也可以很容易地将微服务体系中的任何一个微服务透过Nginx使用公网域名进行服务暴露。例如,随着微服务逻辑从业务上逐步分层,这里所说的分层是指这个微服务体系越来越大,应用本身按照业务线会被划分成多个子系统,例如独立于用户C端微服务系统,我们需要开发一个To B的微服务组,而该微服务组由于功能上独立于C端用户系统,所以我们并不想让其调用链路透过C端Api Gateway,而是想直接将其微服务通过新域名暴露至公网服务,供App端进行调用。像这样的需求,我们只需要使用Consul Template进行一下配置,就能实现Nginx的动态代理转发了。这样从架构运维体验上来讲,使用Consul Template就会让Spring Cloud微服务的部分运维工作变得非常简单了。

Consul Template+Nginx实现微服务部署的高可用

那么接下来,我们就来看看如何利用Consul Template+Nginx这样的组合来实现Spring Cloud微服务部署的高可用吧。这里为了演示简单,小码哥首先在自己的Mac笔记本上安装一个单机版的Consul(Ps:真是的生产环境Consul是集群部署的),下载后将命令文件拷贝至相应目录,并启动Consul如下:

./consul agent -dev

此时访问本机的8500端口,例如:http://127.0.0.1:8500,就能够看到Consul被成功启动来,如图所示:

接下来,我们从Consul Template官方地址:releases.hashicorp.com/consul-temp… Template的可执行文件。并将其解压到/usr/local/bin/目录即可,之后运行:“consul-template -h”命令,如果能够正常执行则说明Consul Template在本机就安装成功了!,

之后作者在Mac笔记本上安装一个Nginx反向代理服务器,下载地址为:nginx.org/en/download…

为安装文件修改权限

chmod a+rwx *

执行编译命令

./configure --without-http_rewrite_module

执行安装命令

make && make install

启动nginx

/usr/local/nginx/sbin/nginx

此时访问本机80端口http://localhost/,如果出现如下画面:

就说明本机nginx服务安装成功了!注意这里作者只是在自己的工作电脑上为了进行演示而进行的基本安装操作,生产Linux环境的安装方式还请大家参考其他更加细节的文章。

在准备完Nginx、Consul及Consul Template之后,那么该如何进行配置呢?此时作者基于Spring Cloud在本地开发来一个微服务,并且将该微服务注册到本地刚才安装的Consul中,这里作者启动两个实例,如下:

此时,在Consul中就注册了名叫wallet服务的两个副本,接下来作者就通过Consul Template的配置模拟下通过Nginx反向代理域名访问wallet服务的接口,并实现负载均衡功能!

一般在正式的生产环境中域名会通过DNS解析到Nginx反向代理服务器中,这里为了模拟测试,我们在Mac笔记本的/private/etc/hosts文件中加一个模拟的域名映射,如下:

127.0.0.1  api.wudimanong.com

接下来我们创建一个consul-template文件模板consul-wallet.tpl,其中的内容就是要把我们在前面启动的wallet微服务通过Nginx暴露出去,内容如下:

{{if service "wallet"}}
server {
    listen  80;
    server_name  ~^wallet\.(.+\.)?wudimanong\.(com|cn)$;
    access_log  /data/logs/nginx/wallet-access.log ;
    error_log  /data/logs/nginx/wallet-error.log ;

    client_max_body_size  1000m;

    location / {
        include proxy.conf;
        proxy_pass http://server-wallet;
    }
}

upstream server-wallet {
{{range service "wallet"}}  server {{.Address}}:{{.Port}};
{{end}}}
{{ end }}

以上文件模板的内容基本上就是和Nginx的配置语法类似,接下来我们启动Consul Template,命令如下:

sudo consul-template -consul-addr "127.0.0.1:8500" -template "/Users/guanliyuan/consul-wallet.tpl:/usr/local/nginx/conf.d/consul-wallet.conf:/usr/local/nginx/sbin/nginx -s reload" > /Users/guanliyuan/logs/wallet-template.log 2>&1 &

启动Consul Template之后我们可以查看通过Consul Template模版生成的Nginx配置文件“/../conf.d/consul-wallet.conf”,代码如下:

server {
    listen  80;
    server_name  ~^wallet\.(.+\.)?wudimanong\.(com|cn)$;
    access_log  /data/logs/nginx/wallet-access.log ;
    error_log  /data/logs/nginx/wallet-error.log ;

    client_max_body_size  1000m;

    location / {
        include proxy.conf;
        proxy_pass http://server-wallet;
    }
}

upstream server-wallet {
  server 192.168.0.106:9090;
  server 192.168.0.106:9091;
}

可以看到Consul Template实际上是为Nginx动态从Consul中获取了服务的地址及端口列表,如果此时我们关掉wallet微服务的一个实例,相应地我们就会从生成的Nginx配置中看到下线的实例的服务地址和端口就被剔除了,代码如下:

server {
    listen  80;
    server_name  ~^wallet\.(.+\.)?wudimanong\.(com|cn)$;
    access_log  /data/logs/nginx/wallet-access.log ;
    error_log  /data/logs/nginx/wallet-error.log ;

    client_max_body_size  1000m;

    location / {
        include proxy.conf;
        proxy_pass http://server-wallet;
    }
}

upstream server-wallet {
  server 192.168.0.106:9091;
}

到这里大家应该是比较清晰地理解Consul Template到底是个什么东西了。它实际上就是通过监听Consul服务,并依据模版中定义的服务名称去获取服务在Consul中实例的地址及端口列表,然后动态地将这些服务的地址及端口准实时地同步到Nginx配置中。示意图如下:

此时,在网络域名正常的情况下我们通过域名访问wallet服务相关的接口了,并且已经由Nginx为我们实现了负载均衡逻辑。与Spring Cloud内部微服务通过Ribbon客户端依赖实现负载均衡相配合,整个Spring Cloud的服务基本运维逻辑就算实现了!