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

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

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

我之前尝试借助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框架

时间: 2024-11-10 07:30:59

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

Consul实践之Consul结合nginx构建高可用可扩展的Web服务

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://dgd2010.blog.51cto.com/1539422/1730439 前文<Consul实践之Consul是什么>讲述了consul是什么,这篇文档是一个Consul实际应用的一个例子,用Consul结合nginx构建高可用可扩展的Web服务.Consul还能做许多其他的事情,可以根据实际需要构思和使用. 方案概述 nginx提供的负载均衡服务同样支持高可用.可扩展的W

使用Node.js配合Nginx实现高负载网络

  这篇文章主要介绍了使用Node.js配合Nginx实现高负载网络,Node的异步加上Nginx的反向代理在性能上实在是给力!需要的朋友可以参考下 在搭建高吞吐量web应用这个议题上,NginX和Node.js可谓是天生一对.他们都是基于事件驱动模型而设计,可以轻易突破Apache等传统web服务器的C10K瓶颈.预设的配置已经可以获得很高的并发,不过,要是大家想在廉价硬件上做到每秒数千以上的请求,还是有一些工作要做的. 这篇文章假定读者们使用NginX的HttpProxyModule来为上游

使用Docker、CoreOS、Mesos部署可扩展的Web应用

使用Docker.CoreOS.Mesos部署可扩展的Web应用 [编者的话]本文作者重点介绍了如何使用Docker.CoreOS.Mesos.Vulcand.对象存储来部署一个可扩展的Web应用,他首先介绍了 为什么要选择这些工具以及与其它工具相比这些工具的优势.紧接着,他通过实际案例演示了整个部署过程,图文并茂,推荐阅读. 介绍 让我们先来讨论一下为什么我决定使用这些软件来展示如何创建一个可扩展的Web基础架构. 为什么选择Docker? 那问题来了,为啥要选择Linux容器?因为相比于虚拟

关于Nginx+Jboss高可用集群的问题

问题描述 有两台linux服务器,准备部署Nginx+Jboss高可用集群,准备在服务器1上安装Nginx和多个Jboss实例,服务器2上也是安装Nginx和多个Jboss实例,Nginx负责静态文件处理和前端调度,静态文件存储于两台服务器可共同访问的存储上.俩个Nginx中只有一个处于工作状态,所有Jboss实例均处于工作状态.实现效果:1.Jboss集群中的实例失效后,前端调度的Nginx负责把请求分发到其他Jboss实例,失效Jboss实例上的session转移到其他实例.2.其中一个Ng

docker学习(6) docker中搭建java服务及nginx反向代理

先看下容器规划: 上图中mysql容器的搭建见上篇博客,service1/2为java rest service,创建脚本如下: docker run -d -h service1 \ -v /Users/yjmyzz/data/service:/opt/service \ --name service1 \ --link mysql:mysql -p 0.0.0.0:9081:8080 java \ java -jar opt/service/spring-boot-rest-framewor

Keeplived如何配置Nginx双机高可用

一.简介 不管是Keepalived还是Heartbeat做高可用,其高可用,都是站在服务器脚本去说的高可用,而不是服务的角度. 也就是说,如果服务器DOWN机或者网络出现故障,高可用是可以实现自动切换的.如果运行的服务,比如Nginx挂掉 这些高可用软件是意识不到的,需要自己写脚本去实现服务的切换. 二.安装配置Keepalived # ./configure # make # make install # cp /usr/local/etc/rc.d/init.d/keepalived /e

《精通Nginx》一1.3 配置Web或者mail服务器

1.3 配置Web或者mail服务器 Nginx是一个独一无二的高性能Web服务器,它也被设计成为一个邮件代理服务器.根据你构建Nginx的目标,可将其配置成一个Web加速器.Web服务器.邮件代理,或者是集所有为一体.你可以将任何服务安装在一个二进制文件中,这样做的好处是可以通过配置文件来设置Nginx服务器的角色,或者根据需要在高性能的环境中安装一个瘦身的二进制Nginx文件. 1.3.1 邮件代理的配置选项 表1-3是邮件模块独有的配置选项. 对于典型的mail代理,我推荐将Nginx配置

[译]深入 NGINX: 为性能和扩展所做之设计

NGINX在web性能上的表现尤为出众,这完全得益于其设计方式,许多web和应用服务器都是基于线程或进程这种简单的架构,NGINX用了一种精妙的事件驱动架构,在现代的硬件上,它可以处理成千上万的并发连接. Inside NGINX中的信息图对高级别的进程架构和NGINX如何在单个进程中处理多个连接进行了深入探讨.本文更进一步地阐述了NGINX的所有工作原理. 背景--NGINX进程模型 要更好的理解这个设计,需要熟悉NGINX的运行过程.NGINX有一个主进程(该进程执行一些特权操作,例如读取配

使用Node.js配合Nginx实现高负载网络_node.js

 在搭建高吞吐量web应用这个议题上,NginX和Node.js可谓是天生一对.他们都是基于事件驱动模型而设计,可以轻易突破Apache等传统web服务器的C10K瓶颈.预设的配置已经可以获得很高的并发,不过,要是大家想在廉价硬件上做到每秒数千以上的请求,还是有一些工作要做的. 这篇文章假定读者们使用NginX的HttpProxyModule来为上游的node.js服务器充当反向代理.我们将介绍Ubuntu 10.04以上系统sysctl的调优,以及node.js应用与NginX的调优.当然,如