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

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
简介:

前文《Consul实践之Consul是什么》讲述了consul是什么,这篇文档是一个Consul实际应用的一个例子,用Consul结合nginx构建高可用可扩展的Web服务。Consul还能做许多其他的事情,可以根据实际需要构思和使用。

方案概述

nginx提供的负载均衡服务同样支持高可用、可扩展的Web服务,但缺点是较依赖于人工。例如传统的nginx负载均衡的配置方式是,在nginx某个include的某个配置文件中配置一个upstream,upstream中配置多个服务节点,每一个服务节点就是一个web应用服务。nginx虽然可以做到对服务节点的健康检查,但是当服务节点增加、减少或者发生状态改变(如负载较大、网络故障、其他故障)时,nginx配置文件是固定写死的,不能动态的感知后端服务节点的服务状态信息,因此需要有一种解决方案能够帮助ngnix动态的感知后端服务节点的服务信息。要想实现这种需求,绝不仅Consul一家,但此例中使用Consul来实现,关于Consul其他的使用案例可以继续学习和研究。

配置概述

此方案用到的组件:Consul、Consul-template、nginx、docker engine、docker-enter、git等,如果构建docker环境以及如何编译安装nginx可以参考《Ubuntu安装Docker引擎和支持HTTPS的docker-registry服务》也可以参考其他网站上的文档或教程。

部署环境:本例子用阿里云的虚拟主机作为测试主机,该测试主机内建有Docker环境,Consul Cluster用docker搭建而成,nginx搭建在测试主机上,consul-template安装在测试主机上,服务应用以容器的形式运行在docker中。注释:consul支持多种部署环境,具体的如何部署可以参考已有的知识库、经验,也可以参考文本自己构思。

下图是整理过的consul应用场景模拟图。用户访问前端的Application也就是UI,前端Application通过App Configuration File从后端Application上获取提供的服务,再返回给用户。后端Application上均安装consul,并以agent的形式运行在服务器上,并将Consul Agent加入到Consul Cluster中。Consul-template与Consul Cluster的Server连接,动态的从Consul的服务信息库汇中拉取后端Application的服务信息,这些服务信息写入到前端Application的配置文件中,在完成一次写入后(即后台服务发生变更时),Consul-template将自动通过命令告知前端应用重新加载,实现前端Application动态发现后端服务以及应用新配置文件的目的。

image 

下图是根据上图延伸来的一个实际的方案,利用Consul结合nginx构建高可用可扩展的Web服务。nginx前端作为负载均衡器使用,它代理了三台能提供web服务的服务器,每一台服务器上均安装consul,并以agent的形式运行在服务器上,并将Consul Agent加入到Consul Cluster中。Consul-template与Consul Cluster的Server连接,动态的从Consul的服务信息库汇中拉取nginx代理的三台服务器的IP、端口号等信息,并将IP地址以及端口号写入到nginx的配置文件中,在完成一次写入后(即后台服务发生变更时),Consul-template将自动将nginx重启加载,实现nginx应用新配置文件的目的。

image

操作步骤

本文假设系统中已经安装好nginx和docker engine以及docker-enter以及git等工具。其操作步骤概括如下:

  1. 构建consul Cluster(Consul 集群)

  2. 构建Web应用服务

  3. 每一个服务应用安装和配置Consul Agent

  4. 安装并配置consul-template使consul-template与nginx联动

  5. 验证与测试

具体地操作步骤如下文所示。

构建consul Cluster(Consul 集群)

构建consul Cluster(Consul 集群)可以部署在docker中,也可以部署在多个物理机中,也可以部署在多个虚拟机中,也可以部署在这些混合环境中。此例最初是为了快速学习Consul而用docker搭建的Consul集群,用其他方式部署也大同小异,可以根据docker的部署步骤反推,具体的可以参考下文分割线中间的部分。

关于docker images的选用。可以通过搜索docker hub,输入consul关键词,搜索所有与consul有关的关键词,根据使用人数(pull次数)或星数(Stars)以及点开details(细节)按钮查看Repo info选项卡中关于该image的详细描述以及使用方法,再根据已有的知识库、经验判断使用哪一个image。此方案中使用progrium/consul作为docker images。

progrium/consul的image地址:https://hub.docker.com/r/progrium/consul/

选用理由如下:

  • 已有方案中有使用progrium/consul的案例,可以供参考;

  • 此镜像的星数和pull次数是最多的,pull次数高达9百万次;

  • 在它的Repo info中详细的介绍了该镜像如何使用以及如何部署consul集群;

  • 此外,该image大小合适,仅有五六十MB,虽然基于busybox,但同样适用于有Linux经验的技术人员。

在progrium提供的方案中提供了三种部署方式:1,试用consul;2.单机环境部署;3.生产环境部署。

Consul官方推荐部署方式可以参考:BOOTSTRAPPING A DATACENTER 以及 Deployment Table

下表中列出了不同集群规模下的群体大小以及容错率,推荐使用3-5台服务器用于部署Consul。为防止在故障发生时造成必不可免的数据损失,单个服务器的部署方案是极不推荐的。


Servers Quorum Size Failure Tolerance
1 1 0
2 2 0
3 2 1
4 3 1
5 3 2
6 4 2
7 4 3


由于环境有限,可用测试的主机的数量低于3,因此只能解决单机环境用docker满足consul的配置要求(尽管此要求并不是强制的,也就是说可以使用一个服务器、两个服务器)。

操作步骤可以参考https://hub.docker.com/r/progrium/consul/网站提供的Testing a Consul cluster on a single host,也可以参考下文。

1
2
3
4
5
6
7
8
9
# Refer: 
https: //hub .docker.com /r/progrium/consul/
     
docker pull progrium /consul    
docker run -d --name node1 -h node1 progrium /consul  -server -bootstrap-expect 3    
JOIN_IP= "$(docker inspect -f '``.`NetworkSettings`.`IPAddress`' node1)"    
docker run -d --name node2 -h node2 progrium /consul  -server - join  $JOIN_IP    
docker run -d --name node3 -h node3 progrium /consul  -server - join  $JOIN_IP    
docker run -d -p 8400:8400 -p 8500:8500 -p 8600:53 /udp  --name node4 -h node4 progrium /consul  - join  $JOIN_IP

经过上述命令,测试主机上的8400、8500以及8600端口就可以使用了,端口作用分别是8400 (RPC), 8500 (HTTP), and 8600 (DNS) ,后面会用到8500。注意,此处的RPC与dubbo定义的RPC有所不同,在Dubbo中RPC用于“远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。”,而在这里的RPC是是Consul Agent与Consul Server通信用的端口。除了以上端口还有其他一些端口,比如8300、8301、8302,这三个是用于Consul内部通信使用的,单个主机环境中这三个端口用不到,所以不需要将这几个端口暴露给测试主机。

以上命令会在docker环境中创建4个容器(node1、node2、node3和node4),其中node1因为-server参数被显式的设置为server,其他的容器被设置成client,并加入到以node1为server的集群中,他们每个节点都回监听接口,但只有node4将其端口与测试主机连接到了一起,这样可以通过访问测试主机上的端口就能获取到consul中存储的已注册服务的服务信息。

经过上述步骤consul集群就算搭建完成了,可以用浏览器访问http://ipaddress:8500/ui/#/dc1/services访问consul的ui控制台界面(说是控制台,但控制管理的功能比较少,目前仅供查看consul集群信息以及k/v数据库的功能)

=========================分割线======================================

非docker环境如何搭建consul?

根据docker容器中运行的命令以及配置文件能够轻松的发现在非docker环境中运行consul的方法,摘录如下:

# node1   

1
/bin/consul  agent -config- dir = /config  -server -bootstrap-expect 3

#192.168.0.7是node1的内网IP   
# node2    

1
/bin/consul  agent -config- dir = /config  -server - join  192.168.0.7

# node3    

1
/bin/consul  agent -config- dir = /config  -server - join  192.168.0.7

# node4    

1
/bin/consul  agent -config- dir = /config  - join  192.168.0.7

# cat /config/consul.json     
{    
"data_dir": "/data",    
"ui_dir": "/ui",    
"client_addr": "0.0.0.0",    
"ports": {    
  "dns": 53    
},    
"recursor": "8.8.8.8",    
"disable_update_check": true    
}

根据上面的consul的json数据,根目录下还有个ui目录,其内容可以通过如下获得:

1
2
3
4
5
6
# for consul web ui   
wget -c 
https: //releases .hashicorp.com /consul/0 .6.0 /consul_0 .6.0_web_ui.zip
     
mkdir  consul_web_ui    
unzip -d consul_web_ui consul_0.6.0_web_ui.zip

 
除了ui以外还有一个/data目录,此目录可以自己建,根据consul命令的提示自己创建。

=========================分割线======================================

构建Web应用服务

构建Web应用服务可以通过多种方式,根据自己的实际情况搭建。比如可以用java语言写一个简单的serverlet也可以nginx做一个Web测试页出来,还可以直接用docker hub上现有的Web程序做测试。

此处可以使用如下的方法快速构建一个Web应用。

1
2
3
4
5
#docker commit jdk8-firstvert jdk8-firstvert_with_consul   
#docker images    
docker run -idt --name firstvertnode1 -h firstvertnode1 jdk8-firstvert_with_consul  /bin/bash     
docker run -idt --name firstvertnode2 -h firstvertnode2 jdk8-firstvert_with_consul  /bin/bash
docker run -idt --name firstvertnode3 -h firstvertnode2 jdk8-firstvert_with_consul  /bin/bash

经过上述命令后,就会生成3个新的容器,每个容器运行着一个java serverlet,可以监听某个端口来提供Web服务。   

每一个服务应用安装和配置Consul Agent

通过docker-enter命令进入每一个容器下载并配置consul

1
2
3
4
5
6
7
8
9
10
# for test    
[ -x  /bin/consul  ] || ( wget -c 
https: //releases .hashicorp.com /consul/0 .6.0 /consul_0 .6.0_linux_amd64.zip
  && unzip -d  /bin  consul_0.6.0_linux_amd64.zip )    
[ -d  /config  ] ||  mkdir  /config    
[ -d  /data  ] ||  mkdir  /data    
# JOIN_IP is 192.168.0.7    
nohup  /bin/consul  agent -config- dir = /config  - join  192.168.0.7 -data- dir  /data  2>&1 > /tmp/consul .log &    
nohup  java -Dfile.encoding=utf-8 -jar FirstVert.x3-1.0-SNAPSHOT-fat.jar 2>&1 > /dev/null  &    
# echo '{"service": {"name": "web", "tags": ["FirstVert"], "port": 8081}}' > /config/FirstVert.json

#下面这个命令是可以通过ping检查与百度网站连接的网络状态,可以加也可以不加   

1
2
3
echo  '{ "check" : { "name" "ping" "script" : " ping  -c1 
www.baidu.com
  2>&1 > /dev/null ", " interval ": " 30s"}}' > /config/ping .json

# 下面的service中name为web是自定义的,可以自己取名字,tags后的FirstVert也是自己取的,脚本是用来检测此服务是否正常的,根据语义应该是根据函数返回值判断的   

1
echo  '{"service": {"name": "web", "tags": ["FirstVert"], "port": 8081, "check": {"script": "curl localhost:8081 >/dev/null 2>&1", "interval": "10s"}}}'  > /config/FirstVert .json

#更新consul数据文件(相当于向consul注册服务)后,需要重新运行consul agent

1
2
killall consul   
nohup  /bin/consul  agent -config- dir = /config  - join  192.168.0.7 -data- dir  /data  2>&1 > /tmp/consul .log &

如果想简单的测试一下是否好用,可以用以下命令进行测试,

1
while  : ;  do  curl http: //ipaddress :port -w %{http_code} -s -o  /dev/null sleep  1;  done

  

安装并配置consul-template使consul-template与nginx联动

# Refer: https://github.com/hashicorp/consul-template    
# Refer: https://releases.hashicorp.com/consul-template/0.12.0/    
https://github.com/hashicorp/consul-template/releases    

1
2
3
4
5
6
wget -c 
https: //releases .hashicorp.com /consul-template/0 .12.0 /consul-template_0 .12.0_linux_amd64.zip
     
unzip -d . consul-template_0.12.0_linux_amd64.zip    
cp  consul-template  '/bin'    
rm  -rf consul*

# ready for test

# 把下面的{ {range service "web"}}改成上面修改的service的名称,把server_name改成要监听的主机名或IP地址

# 负载均衡算法由nginx控制,具体的可以查阅nginx相关手册和网上的其他资料   
# Refer: nohup /bin/consul agent -config-dir=/config -join 192.168.0.7 -data-dir /data 2>&1 >/tmp/consul.log &    
# Refer: https://github.com/DingGuodong/consul-template#examples    

1
vim  /root/nginx_web .ctmpl

编辑内容如下

upstream web {    
    ip_hash;    
    # Refer: http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream    
    # least_conn;    
    # least_time;    
{ {range service "web"}}    
    server ``.`Address`:``.`Port` fail_timeout=0;    
`end`    
    keepalive 64;    
}

server {   
    listen 80;    
    server_name ipaddress;

    location / {   
        client_max_body_size    0;    
        proxy_connect_timeout 300s;    
        proxy_send_timeout   900;    
        proxy_read_timeout   900;    
        proxy_buffer_size    32k;    
        proxy_buffers      4 32k;    
        proxy_busy_buffers_size 64k;    
        proxy_redirect     off;    
        proxy_hide_header  Vary;    
        proxy_set_header   Accept-Encoding '';    
        proxy_set_header   Host   $host;    
        proxy_set_header   Referer $http_referer;    
        proxy_set_header   Cookie $http_cookie;    
        proxy_set_header   X-Real-IP  $remote_addr;    
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;    
        proxy_set_header   Host $host;    
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;           
        proxy_headers_hash_max_size 51200;    
        proxy_headers_hash_bucket_size 6400;    
        proxy_pass               }    
}

# -dry表示仅运行此命令,但不实际执行写入文件的命令,此处是指不根据模版修改文件,不执行nginx -s reload命令

1
consul-template -consul 127.0.0.1:8500 -template  /root/nginx_web .ctmpl: /usr/local/nginx/conf/vhost/http_temp_port_80 .conf: "/usr/local/nginx/sbin/nginx -s reload"  -dry

#通过此命令可以将consul-template 放到后台执行

1
nohup  consul-template -consul 127.0.0.1:8500 -template nginx_web.ctmpl: /usr/local/nginx/conf/vhost/http_temp_port_80 .conf: "/usr/local/nginx/sbin/nginx -s reload"  2>&1 > /tmp/consul-template .log &

上述命令执行后可以通过ps -ef | grep consul和查看/tmp/consul-template.log日志文件,查看consul-template的运行情况,也可以直接通过测试的手段来检测consul-template的运行情况。    

验证与测试

经过以上步骤搭建完成后,可以访问nginx上配置好的server_name,以及consul的ui即http://ipaddress:8500/ui/#/dc1/services来查看效果。

可以尝试分别测试如下内容:

容器停止后,nginx的配置文件的内容,nginx的访问情况;

容器创建并启动consul agent后,nginx的配置文件的内容,nginx的访问情况;

发现容器出现任何非passing的情况,都会导致从nginx配置文件中移除;容器启动并配置正常后,nginx配置文件更新,容器可以被访问。这说明是非常符合预期需求的。

在初读consul的文档和查阅相关资料后,还尚未发现依赖于consul自身就能实现,提供根据服务节点的负载或健康状况而增加、移除服务节点的功能。这个有待于进一步查看和研究。

tag:consul测试方案,consul配置,consul RPC,consul搭建,consul实例

--end--




本文转自 urey_pp 51CTO博客,原文链接:http://blog.51cto.com/dgd2010/1730439,如需转载请自行联系原作者



相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
1月前
|
XML JSON 数据安全/隐私保护
Web服务
【10月更文挑战第18天】Web服务
48 9
|
1月前
|
XML JSON 安全
Web服务是通过标准化的通信协议和数据格式
【10月更文挑战第18天】Web服务是通过标准化的通信协议和数据格式
150 69
|
14天前
|
Go UED
Go Web服务中如何优雅平滑重启?
在生产环境中,服务升级时如何确保不中断当前请求并应用新代码是一个挑战。本文介绍了如何使用 Go 语言的 `endless` 包实现服务的优雅重启,确保在不停止服务的情况下完成无缝升级。通过示例代码和测试步骤,详细展示了 `endless` 包的工作原理和实际应用。
34 3
|
15天前
|
JSON Go UED
Go Web服务中如何优雅关机?
在构建 Web 服务时,优雅关机是一个关键的技术点,它确保服务关闭时所有正在处理的请求都能顺利完成。本文通过一个简单的 Go 语言示例,展示了如何使用 Gin 框架实现优雅关机。通过捕获系统信号和使用 `http.Server` 的 `Shutdown` 方法,我们可以在服务关闭前等待所有请求处理完毕,从而提升用户体验,避免数据丢失或不一致。
16 1
|
20天前
|
监控 前端开发 JavaScript
探索微前端架构:构建可扩展的现代Web应用
【10月更文挑战第29天】本文探讨了微前端架构的核心概念、优势及实施策略,通过将大型前端应用拆分为多个独立的微应用,提高开发效率、增强可维护性,并支持灵活的技术选型。实际案例包括Spotify和Zalando的成功应用。
|
21天前
|
XML 安全 PHP
PHP与SOAP Web服务开发:基础与进阶教程
本文介绍了PHP与SOAP Web服务的基础和进阶知识,涵盖SOAP的基本概念、PHP中的SoapServer和SoapClient类的使用方法,以及服务端和客户端的开发示例。此外,还探讨了安全性、性能优化等高级主题,帮助开发者掌握更高效的Web服务开发技巧。
|
1月前
|
XML JSON 安全
定义Web服务
【10月更文挑战第18天】定义Web服务
62 12
|
28天前
|
负载均衡 应用服务中间件 nginx
基于Nginx和Consul构建自动发现的Docker服务架构——非常之详细
通过使用Nginx和Consul构建自动发现的Docker服务架构,可以显著提高服务的可用性、扩展性和管理效率。Consul实现了服务的自动注册与发现,而Nginx则通过动态配置实现了高效的反向代理与负载均衡。这种架构非常适合需要高可用性和弹性扩展的分布式系统。
28 4
|
29天前
|
负载均衡 应用服务中间件 nginx
基于Nginx和Consul构建自动发现的Docker服务架构——非常之详细
通过使用Nginx和Consul构建自动发现的Docker服务架构,可以显著提高服务的可用性、扩展性和管理效率。Consul实现了服务的自动注册与发现,而Nginx则通过动态配置实现了高效的反向代理与负载均衡。这种架构非常适合需要高可用性和弹性扩展的分布式系统。
36 3
|
1月前
|
前端开发 Java API
JAVA Web 服务及底层框架原理
【10月更文挑战第1天】Java Web 服务是基于 Java 编程语言用于开发分布式网络应用程序的一种技术。它通常运行在 Web 服务器上,并通过 HTTP 协议与客户端进行通信。
26 1
下一篇
无影云桌面