使用Consul+Consul template+Docker+Registrator+nginx实现动态服务注册和服务发现

写在最前面:本文尝试使用Docker、Registrator、Consul、Consul-template和Nginx实现可扩展的、支持服务注册、服务发现的架构。本文不涉及这些软件的具体实现方法,是对其功能进行探索。

概述

Docker,容器(Container)技术近年来为什么会兴起?我的理解是因为整个世界都是网络了,既然有网络应用的消费者,那必须就有网络应用的生产者,容器技术就是生产者为了解脱自己的痛苦而创造的一个东西,背后的思想是创建软件程序可移植的轻量容器。通俗地讲,开发者在开发环境中开发自己的应用,要部署到实际生产线是一件非常复杂的事情,docker的出现,使得开发者一切操作都在docker中进行,把docker搬到生产环境中即可使用,非常方便。软件的出现的目的总是让使用者更加方便,所以学习一下docker还是会给你一种新的启发。

Consul,Consul是HahsiCorp开发的一个服务发现与配置的项目,Consul实质上以KV形式保存数据,你可以理解Consul就是你的服务管家,这个管家不止可以创建Cluster,还有良好的Web界面,值得推荐。这时不得不提到另一个大名鼎鼎的动物园管家,Zookeeper,在公司实际项目中,zk来做服务的发现注册已经有一套方案,本文的方法算是另一条路吧,不存在好坏之分。

Consul-template,他在监控着Consul,当其发现其中的服务项有变化时,更新文件并执行操作。譬如本文中要做的,更新nginx配置文件,并对nginx进行优雅地重启。

Registrator,原名叫Docksul,看名字就知道,他和docker分不开,本文非要引入docker的原因也是因为他,他是一个为docker而设计的服务注册项目,他监听跨主机运行的容器的启动和停止,检查并向Consul注册。其实本文中其他的项目都可以单独在宿主机上运行,只是这个Registrator不行,所以最后的方案还是经过考虑再选择,毕竟学习docker也是需要一定的成本的。

Nginx,这个软件就不用介绍了,大名鼎鼎,做静态文件服务器、反向代理、路由选择、负载均衡,支持极高并发,主流是nginx+tomcat?这个我不太清楚业界主流是Nginx加什么。多嘴一句,如果有兴趣阅读Nginx源码,要找到合适的方法,个人觉得还是彻底先了解功能后再进行源码阅读会比较好。

大体思路

1.启动Consul,Consul直接在宿主机上运行可以,在容器中运行也可以,看需求,本文后面的实际操作中,将Consul放到了Docker中。

2.Service A、Service B、Service C在启动时向Consul中注册自己,其他服务启动时也主动向Consul注册。

3.运行Consul template,正如概述中讲的,本文中template的作用就是更新Nginx配置文件并重启Nginx,我原本想这些组件都在Docker中运行,但是奈何我国国情,我真的pull不下来Consul template,所以就只能在宿主机上运行了。FUCK the GFW!

4.Nginx,做负载均衡,要起得作用是动态的把网络消费者的请求转发到后台的Docker中。

大体流程图如下,配合着上述大体思路,我觉得应该能看懂了。
Servive Discovery

实际操作

实验环境:Ubuntu 14.04 64位,Docker官方强调64位了,也许你32的也能安上,但是pull下的很多东西不能用,比较蛋疼。

1.docker的安装和使用,自行Google或Bing。

2.构建一个web服务,此处参考

web服务器的Dockerfile如下:(注意:python3中好像是http.server)

FROM python:2.7
EXPOSE 80
CMD ["python","-m","SimpleHTTPServer" ]

在Dockerfile所在的文件夹下执行,创建以个名为simplehttpserver的镜像

docker build -t simplehttpserver .

利用上面创建的镜像构建容器:

docker run -it -p 8000:80 simplehttpserver

即可通过浏览器或者curl访问。

3.docker中运行Consul(此处正式开始操作,第2步只是基础服务,要在系统跑起来之后再注册服务)

docker run -it -h node -p 8500:8500 -p 8600:53/udp progrium/consul -server -bootstrap -advertise 127.0.0.1 -log-level debug

运行之后,Consul是自带UI界面的,所以通过浏览器可以访问。

4.docker中运行Registrator

docker run -d --name=registratror --net=host --volume=/var/run/docker.sock:/tmp/docker.sock gliderlabs/registrator consul://127.0.0.1:8500

5.Host中运行Consul-template

./consul-template -consul 127.0.0.1:8500 "/etc/nginx/conf.d/test.ctmpl:/etc/nginx/config.d/test.conf:nginx -s reload"

consul-template指定了模板的位置和生成文件的存放位置,然后对nginx进行重启就可以了。

上述步骤中各个模块的具体参数可以查看help。

One more thing…

这个框架中的关键是Consul,这里用到了Consul的服务注册,个人感觉Consul服务注册有三种方法吧

A.通过编写配置文件(json),指定配置文件的存放目录 –config-dir

B.通过Consul HTTP API,在实际程序中调用,当程序运行起来的时候自动注册

C.第三方注册,结合Docker使用,使用Registrator这样的工具

其中的优缺点想必大家也都了解了,通过A是要手动编写json配置文件并向Consul发送一个reload命令,我在想这样做好像不太合适,我们的目的是自动化的实现服务注册,在本文的应用场景下,与其重启Consul,还不如来个nginx -s reload,反正总有一个要重启嘛。B方案目前还没有实践,但可以想到也是会有问题的,在你程序里平白无辜加一段控制代码,谁都不愿意。C方案正是本文的实践方法,可以实现完全动态,但依赖于Docker平台和Registrator组件。