使用Docker、Registrator、Consul、Consul Template和Nginx实现高可扩展的Web框架

简介: 本文讲的是使用Docker、Registrator、Consul、Consul Template和Nginx实现高可扩展的Web框架,【编者的话】Consul是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件,由 HashiCorp 公司用Go语言开发,基于 Mozilla Public License 2.0 的协议开源。
本文讲的是使用Docker、Registrator、Consul、Consul Template和Nginx实现高可扩展的Web框架 【编者的话】Consul是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件,由 HashiCorp 公司用Go语言开发,基于 Mozilla Public License 2.0 的协议开源。本文介绍了如何使用Consul将多个Docker容器组合起来,以提供一个高可扩展的Web服务。
docker_whale.png_1411805342_.jpg_1421807584_.jpg

当你开始将容器拼装起来构建你的系统的时候,你会发现Docker非常有趣。最近,我在玩 Consul ,并尝试用它来构建一个高可扩展的Web应用框架。Consul是 HashiCorp Vagrant 的创建者)开发的一个 服务发现与配置 项目。

我之前尝试借助SRV的记录使用Consul来创建一个可扩展的框架(详情请见: here ),但我发现这种方式有点复杂。而我追求简单,所以我又发现了 Consul Template ,当添加或者移除服务时,Consul Template可以通过连接Consul更新配置并重启应用。

在这篇文章中,我将会讲述如何使用Docker将Consul、Consul Template、Registrator和Nginx组装成一个值得信任且可扩展的框架——DR CoN。一旦组装完成,DR CoN就可以让你在这个框架中添加和移除服务,关键是你不需要重写任何配置,也不需要重启任何服务,一切都能正常运行!

Docker

Docker在LXC的基础上(Linux Containers)上包装了一些API,所以它只能运行在Linux上(注[1])。由于我使用的是OS X操作系统(读者中可能大部分人都是),为此我写了 “ 通过Boot2Docker在OSX上运行Docker ”这篇文章,以下是简要介绍:
brew install boot2docker
boot2docker init  
boot2docker up

执行之后,将在Ubuntu上启一个虚拟机来运行Docker daemon。为了连上daemon,执行以下命令:
export DOCKER_IP=`boot2docker ip`  
export DOCKER_HOST=`boot2docker socket`

你可以通过执行下述命令来验证Docker是否成功安装:
docker ps

通过Docker构建一个简单的Web服务

我们需要一个服务来测试Dr Con这个框架。为此,让我们开始构建一个我了解的简单服务(详情请见 此文 )。创建一个 Dockerfile 文件,将以下内容写入其中:
FROM  python:3  
EXPOSE  80  
CMD ["python", "-m", "http.server"]

在Dockerfile文件所在目录下执行以下命令:
docker build -t python/server .

执行后,将创建一个名为  python/server  的镜像,通过执行以下命令运行一个容器:
docker run -it \
-p 8000:80 python/server

我们可以通过 curl 命令调用这个简单服务来测试它是否能够正常运行:
curl $DOCKER_IP:8000

Consul

Consul是一个拥有DNS和HTTP API的服务。它还有很多其它功能,例如服务健康检测、跨主机集群构建和“键-值”对存储库。执行以下命令在Docker container中运行Consul:
docker run -it -h node \
 -p 8500:8500 \
 -p 8600:53/udp \
 progrium/consul \
 -server \
 -bootstrap \
 -advertise $DOCKER_IP \
 -log-level debug

如果你通过浏览器能够访问 $DOCKER_IP:8500 ,你将在控制面板上看到Consul中已经注册的所有服务。

我们能够通过 curl 向Consul的Web API注册一个服务:
curl -XPUT \
$DOCKER_IP:8500/v1/agent/service/register \
-d '{
 "ID": "simple_instance_1",
 "Name":"simple",
 "Port": 8000, 
 "tags": ["tag"]
}'

然后,我们可以通过  dig  命令查询Consul为这个提供的DNS API:
dig @$DOCKER_IP -p 8600 simple.service.consul

执行后,结果如下:
; <<>> DiG 9.8.3-P1 <<>> simple.service.consul
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39614
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;simple.service.consul.        IN    A

;; ANSWER SECTION:
simple.service.consul.    0    IN    A    192.168.59.103

;; Query time: 1 msec
;; SERVER: 192.168.59.103#53(192.168.59.103)
;; WHEN: Mon Jan 12 15:35:01 2015
;; MSG SIZE  rcvd: 76

等等,这有个问题,服务的端口号在哪?很遗憾,DNS的记录中并没有返回服务的端口号。为了获取端口号,我们必须检查SRV记录:
dig @$DOCKER_IP -p 8600 SRV simple.service.consul

执行后,结果如下:
; <<>> DiG 9.8.3-P1 <<>> SRV simple.service.consul
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3613
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; QUESTION SECTION:
;simple.service.consul.        IN    SRV

;; ANSWER SECTION:
simple.service.consul.    0    IN    SRV    1 1 8000 node.node.dc1.consul.

;; ADDITIONAL SECTION:
node.node.dc1.consul.    0    IN    A    192.168.59.103

;; Query time: 1 msec
;; SERVER: 192.168.59.103#53(192.168.59.103)
;; WHEN: Mon Jan 12 15:36:54 2015
;; MSG SIZE  rcvd: 136

SRV记录很难用,因为很多技术不支持它们。

srv-router 这个容器被Consul和Nginx用来路由访问请求到相应服务(详情请见: here )。但是,下面我们将介绍一种更简单的方式让Nginx路由这些请求到相应服务。

Registrator

在Docker容器启动后,Registrator配置好相应的环境变量并将这个容器注册到Consul上,示例如下:
docker run -it \
-v /var/run/docker.sock:/tmp/docker.sock \
-h $DOCKER_IP progrium/registrator \
consul://$DOCKER_IP:8500

Registrator启动后,我们运行一个服务:
docker run -it \
-e "SERVICE_NAME=simple" \
-p 8000:80 python/server

命令执行后,这个服务被自动添加到Consul,同理,如果我们关闭这个服务,它在Consul上会被自动移除。由于Registrator不需要我们手动将服务注册到Consul,因此它是DR CoN需要组装的第一部分。

Consul Template

Consul Template 的作用是,当它发现Consul上的服务有变化时,它会利用Consul更新文件并执行相应的命令。

比如说,它能够重写 nginx.conf 这个文件,将所有服务的路由信息列入其中,然后重新加载Nginx的配置,使得多个相似服务达到负载均衡,或者给多种服务提供一个单一的终端。

我对这个Docker容器做了如下修改(详情请见这里):
FROM nginx:1.7

#Install Curl
RUN apt-get update -qq && apt-get -y install curl

#Download and Install Consul Template
ENV CT_URL http://bit.ly/15uhv24
RUN curl -L $CT_URL | \
tar -C /usr/local/bin --strip-components 1 -zxf -

#Setup Consul Template Files
RUN mkdir /etc/consul-templates
ENV CT_FILE /etc/consul-templates/nginx.conf

#Setup Nginx File
ENV NX_FILE /etc/nginx/conf.d/app.conf

#Default Variables
ENV CONSUL consul:8500
ENV SERVICE consul-8500

# Command will
# 1. Write Consul Template File
# 2. Start Nginx
# 3. Start Consul Template

CMD echo "upstream app {                 \n\
  least_conn;                            \n\
  {{range service \"$SERVICE\"}}         \n\
  server  {{.Address}}:{{.Port}};        \n\
  {{else}}server 127.0.0.1:65535;{{end}} \n\
}                                        \n\
server {                                 \n\
  listen 80 default_server;              \n\
  location / {                           \n\
    proxy_pass http://app;               \n\
  }                                      \n\
}" > $CT_FILE; \
/usr/sbin/nginx -c /etc/nginx/nginx.conf \
& CONSUL_TEMPLATE_LOG=debug consul-template \
  -consul=$CONSUL \
  -template "$CT_FILE:$NX_FILE:/usr/sbin/nginx -s reload";

下载这个Dockerfile,请点击这里

注意: 上面的 \n\ 表示另起一行,并且为Docker的多行命令去除换行。

这个Docker容器将会运行Consul Template和Nginx,当服务有变化时,它将重写Nginx的 app.conf 文件并且重新加载Nginx。

通过以下命令构建这个容器:
docker build -t drcon .

然后,启动容器:
docker run -it \
-e "CONSUL=$DOCKER_IP:8500" \
-e "SERVICE=simple" \
-p 80:80 drcon

SERVICE  选项用来指定Consul上的服务。因此,上面这个DR CoN 容器将会通过所有命名为  simple  的服务来达到负载均衡。

组装到一起

现在让我们把一切都组装起来。

运行Consul:
docker run -it -h node \
 -p 8500:8500 \
 -p 53:53/udp \
 progrium/consul \
 -server \
 -bootstrap \
 -advertise $DOCKER_IP

运行Registrator:
docker run -it \
-v /var/run/docker.sock:/tmp/docker.sock \
-h $DOCKER_IP progrium/registrator \
consul://$DOCKER_IP:8500

运行DR CoN:
docker run -it \
-e "CONSUL=$DOCKER_IP:8500" \
-e "SERVICE=simple" \
-p 80:80 drcon

执行  curl $DOCKER_IP:80  命令,结果如下:
curl: (52) Empty reply from server

现在开启  simple  的服务:
docker run -it \
-e "SERVICE_NAME=simple" \
-p 8000:80 python/server

执行后,将发生:
  1. Registrator将这个服务注册到Consul;
  2. Consul Template重写nginx.conf,然后重新加载配置。

现在执行 curl $DOCKER_IP:80 将成功路由到这个服务。

如果我们在其他端口上启动另一个simple服务:
docker run -it \
-e "SERVICE_NAME=simple" \
-p 8001:80 python/server

请求将通过这两个simple服务进行负载均衡。

有趣的是,我们可以执行 while true; do curl $DOCKER_IP:80; sleep 1; done 这个脚本,当关闭或者启动simple服务时,脚本仍在快速运行且所有请求都能正常进行。

总结

借助Docker,描述、分布和实现DR CoN这类框架变得更加容易,当然也少不了Consul这么好用的工具。使用Docker更加强大的工具来组装服务是非常有趣和有用的,现在我就能创建一种横向可扩展的框架,并且一切都能正常运行。

注[1]:  Docker在1.2版本之后就默认使用libcontainer,而不是LXC,虽然Docker支持LXC。由于不论libcontainer和LXC都是基于Linux Kernel中的namespace和Cgroup,所以现在只能运行在Linux上。

原文链接:Scalable Architecture DR CoN: Docker, Registrator, Consul, Consul Template and Nginx(翻译: 肖远昊 校对:李颖杰)

===========================

译者介绍

肖远昊,硕士研究生,就读于北京航空航天大学计算机学院ACT实验室,目前从事虚拟化、云计算方向的研究。希望通过DockerOne与大家一起交流和学习Docker。

原文发布时间为:2015-03-26
本文作者:xiaoyh 
本文来自云栖社区合作伙伴DockerOne,了解相关信息可以关注DockerOne。
原文标题:使用Docker、Registrator、Consul、Consul Template和Nginx实现高可扩展的Web框架
目录
相关文章
|
10天前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
【4月更文挑战第9天】本文对比了Python三大Web框架Django、Flask和Pyramid。Django功能全面,适合快速开发,但学习曲线较陡;Flask轻量灵活,易于入门,但默认配置简单,需自行添加功能;Pyramid兼顾灵活性和可扩展性,适合不同规模项目,但社区及资源相对较少。选择框架应考虑项目需求和开发者偏好。
|
17天前
|
前端开发 应用服务中间件 nginx
Nginx配置详解Docker部署Nginx使用Nginx部署vue前端项目
Nginx配置详解Docker部署Nginx使用Nginx部署vue前端项目
78 0
|
25天前
|
前端开发 应用服务中间件 nginx
使用Docker快速搭建Web服务器Nginx
本文指导如何使用Docker快速搭建Nginx服务器。首先,通过`docker pull`命令获取Nginx镜像,然后以容器形式运行Nginx并映射端口。通过挂载目录实现本地文件与容器共享,便于自定义网页。使用`docker ps`检查运行状态,访问IP:8088确认部署成功。最后,介绍了停止、删除Nginx容器的命令,强调Docker简化了服务器部署和管理。
39 0
|
4天前
|
前端开发 数据挖掘 API
使用Python中的Flask框架进行Web应用开发
【4月更文挑战第15天】在Python的Web开发领域,Flask是一个备受欢迎的轻量级Web框架。它简洁、灵活且易于扩展,使得开发者能够快速地构建出高质量的Web应用。本文将深入探讨Flask框架的核心特性、使用方法以及在实际开发中的应用。
|
13天前
|
应用服务中间件 nginx Docker
docker实现Nginx
通过以上步骤,你可以使用Docker来快速搭建并运行Nginx服务器,而且可以根据需要进行自定义配置和持久化数据。 买CN2云服务器,免备案服务器,高防服务器,就选蓝易云。百度搜索:蓝易云
12 1
|
16天前
|
前端开发 安全 Java
使用Java Web框架:Spring MVC的全面指南
【4月更文挑战第3天】Spring MVC是Spring框架的一部分,用于构建高效、模块化的Web应用。它基于MVC模式,支持多种视图技术。核心概念包括DispatcherServlet(前端控制器)、HandlerMapping(请求映射)、Controller(处理请求)、ViewResolver(视图解析)和ModelAndView(模型和视图容器)。开发流程涉及配置DispatcherServlet、定义Controller、创建View、处理数据、绑定模型和异常处理。
使用Java Web框架:Spring MVC的全面指南
|
20天前
|
前端开发 JavaScript 数据管理
描述一个使用Python开发Web应用程序的实际项目经验,包括所使用的框架和技术栈。
使用Flask开发Web应用,结合SQLite、Flask-SQLAlchemy进行数据管理,HTML/CSS/JS(Bootstrap和jQuery)构建前端。通过Flask路由处理用户请求,模块化代码提高可维护性。unittest进行测试,开发阶段用内置服务器,生产环境可选WSGI服务器或容器化部署。实现了用户注册登录和数据管理功能,展示Python Web开发的灵活性和效率。
14 4
|
30天前
|
数据库
最全三大框架整合(使用映射)——struts.xml和web.xml配置
最全三大框架整合(使用映射)——数据库资源文件jdbc.properties
9 0
|
1月前
|
NoSQL 关系型数据库 MySQL
Docker安装详细步骤及相关环境安装配置(mysql、jdk、redis、自己的私有仓库Gitlab 、C和C++环境以及Nginx服务代理)
Docker安装详细步骤及相关环境安装配置(mysql、jdk、redis、自己的私有仓库Gitlab 、C和C++环境以及Nginx服务代理)
194 0
|
1月前
|
前端开发 API 网络架构
Python 如何开发出RESTful Web接口,DRF框架助力灵活实现!
Python 如何开发出RESTful Web接口,DRF框架助力灵活实现!