Consul實踐之Consul結合nginx構建高可用可擴展的Web服務

前文《Consul實踐之Consul是什麼》講述了consul是什麼,這篇文檔是一個Consul實際應用的一個例子,用Consul結合nginx構建高可用可擴展的Web服務。Consul還能作許多其餘的事情,能夠根據實際須要構思和使用。
html

方案概述

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服務》也能夠參考其餘網站上的文檔或教程。java

部署環境:本例子用阿里雲的虛擬主機做爲測試主機,該測試主機內建有Docker環境,Consul Cluster用docker搭建而成,nginx搭建在測試主機上,consul-template安裝在測試主機上,服務應用以容器的形式運行在docker中。註釋:consul支持多種部署環境,具體的如何部署能夠參考已有的知識庫、經驗,也能夠參考文本本身構思。node

下圖是整理過的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動態發現後端服務以及應用新配置文件的目的。linux

p_w_picpath 

下圖是根據上圖延伸來的一個實際的方案,利用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應用新配置文件的目的。nginx

p_w_picpath

操做步驟

本文假設系統中已經安裝好nginx和docker engine以及docker-enter以及git等工具。其操做步驟歸納以下:git

  1. 構建consul Cluster(Consul 集羣)github

  2. 構建Web應用服務web

  3. 每個服務應用安裝和配置Consul Agent算法

  4. 安裝並配置consul-template使consul-template與nginx聯動

  5. 驗證與測試

具體地操做步驟以下文所示。

構建consul Cluster(Consul 集羣)

構建consul Cluster(Consul 集羣)能夠部署在docker中,也能夠部署在多個物理機中,也能夠部署在多個虛擬機中,也能夠部署在這些混合環境中。此例最初是爲了快速學習Consul而用docker搭建的Consul集羣,用其餘方式部署也大同小異,能夠根據docker的部署步驟反推,具體的能夠參考下文分割線中間的部分。

關於docker p_w_picpaths的選用。能夠經過搜索docker hub,輸入consul關鍵詞,搜索全部與consul有關的關鍵詞,根據使用人數(pull次數)或星數(Stars)以及點開details(細節)按鈕查看Repo info選項卡中關於該p_w_picpath的詳細描述以及使用方法,再根據已有的知識庫、經驗判斷使用哪個p_w_picpath。此方案中使用progrium/consul做爲docker p_w_picpaths。

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

選用理由以下:

  • 已有方案中有使用progrium/consul的案例,能夠供參考;

  • 此鏡像的星數和pull次數是最多的,pull次數高達9百萬次;

  • 在它的Repo info中詳細的介紹了該鏡像如何使用以及如何部署consul集羣;

  • 此外,該p_w_picpath大小合適,僅有五六十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,也能夠參考下文。

# 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、830一、8302,這三個是用於Consul內部通訊使用的,單個主機環境中這三個端口用不到,因此不須要將這幾個端口暴露給測試主機。

以上命令會在docker環境中建立4個容器(node一、node二、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  

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

#192.168.0.7是node1的內網IP  
# node2    

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

# node3    

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

# node4    

/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目錄,其內容能夠經過以下得到:

# 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應用。

#docker commit jdk8-firstvert jdk8-firstvert_with_consul   
#docker p_w_picpaths    
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

# 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檢查與百度網站鏈接的網絡狀態,能夠加也能夠不加  

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

# 下面的service中name爲web是自定義的,能夠本身取名字,tags後的FirstVert也是本身取的,腳本是用來檢測此服務是否正常的,根據語義應該是根據函數返回值判斷的  

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

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

若是想簡單的測試一下是否好用,能夠用如下命令進行測試,

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    

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    

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          http://web/;    
    }    
}

# -dry表示僅運行此命令,但不實際執行寫入文件的命令,此處是指不根據模版修改文件,不執行nginx -s reload命令

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 放到後臺執行

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--

相關文章
相關標籤/搜索