負載均衡之nginx+consul(自動更新路由)


前幾篇先是記載了如何通過nginx配置服務負載均衡,后面記載了如何通過 ocelot 配置 服務負載均衡,分別介紹了用webapi注冊服務以及配置文件注冊服務,通過ocelot webapi + consul 配置負載均衡系列學習完畢。

然而nginx負載均衡沒有服務發現,依然不能用生產環境,本篇將介紹如何通過 nginx+consul 配置多台服務器的負載均衡並支持服務發現。

試驗背景和目的:一個微服務,有一個網關入口,如果網關出現故障,那么整個微服務馬上癱瘓,那么我們有必要把網關布署在多台服務器上,如果其中有一台出現故障,還有其他服務器在起到微服務網關角色。

下面依然是在同一台linux機子上模似和試驗。

內容包括:

1. nginx服務,做負載均衡

2. consul服務,做服務發現

3. consul template,做動態改變nginx配置並重啟nginx服務

4. 3個網關webapi,分別是

 192.168.1.23:8101

 192.168.1.23:8102

 192.168.1.23:8103

 

(在展開試驗步驟之前,對背景進行大概的介紹是非常重要,我發現很多技術文章一上來二話不說就是貼代碼)

 

1. 安裝 consul 

$ wget https://releases.hashicorp.com/consul/1.4.4/consul_1.4.4_linux_amd64.zip
$ sudo apt-get install unzip


$ unzip consul_1.4.4_linux_amd64.zip
$ sudo mv consul /usr/local/bin/consul

以上命令,在官網下了個包,然后解壓了一下,里面只有一個 consul文件,把文件移到了/usr/local/bin/consul。
 
安裝完畢之后,檢查 
$ consul members
 
發現consul 服務還沒開啟

 

2. 開啟consul 服務,並將3個API服務注冊進去
 
先准備好注冊文件 service.json,放在 /consul/testservices


{
  "encrypt": "Wd7HAMtcgg5RQ2hZhHE9xw==",
  "services": [
    {
      "id": "api1",
      "name": "apigateway",
      "tags": [ "apigateway" ],
      "address": "192.168.1.23",
      "port": 8101,
      "checks": [
        {
          "id": "ApiServiceA_Check",
          "name": "ApiServiceA_Check",
          "http": "http://192.168.1.23:8101/health",
          "interval": "10s",
          "tls_skip_verify": false,
          "method": "GET",
          "timeout": "1s"
        }
      ]
    },
    {
      "id": "api2",
      "name": "apigateway",
      "tags": [ "apigateway" ],
      "address": "192.168.1.23",
      "port": 8102,
      "checks": [
        {
          "id": "ApiServiceB_Check",
          "name": "ApiServiceB_Check",
          "http": "http://192.168.1.23:8102/health",
          "interval": "10s",
          "tls_skip_verify": false,
          "method": "GET",
          "timeout": "1s"
        }
      ]
    }
  ]
}

運行下面的命令:
 
consul agent -server -ui -bootstrap-expect=1 -data-dir=/tmp/consul -node=consul-1 -client=0.0.0.0 -bind=0.0.0.0 -datacenter=dc1 -config-dir=/consul/testservices &

 

3、安裝 consul-template, 

$ wget https://releases.hashicorp.com/consul-template/0.19.3/consul-template_0.19.3_linux_amd64.zip
$ unzip consul-template_0.19.3_linux_amd64.zip
$ mv consul-template /usr/bin/

    測試一下安裝有沒有成功:

$ consul-template -v

4、創建一個consul 模板文件

文件內容:

upstream ocelot {
    {{range service "apigateway"}}
    server {{ .Address }}:{{ .Port }};
    {{ end }}
}


server {
        listen       8105;
        location / {
            proxy_pass   http://ocelot ;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection keep-alive;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_cache_bypass $http_upgrade;

        }

  }

相比之前寫死下游服務節點:

 upstream ocelot {
      server localhost:8104;
      server localhost:8102;
      server localhost:8103;

    }

現在這塊的內容,將會動態地去consul服務數據庫中讀取,注意服務名稱,"apigateway", 這個名稱是注冊到consul時所用的 service name。

 

模板准備好之后,要被nginx配置所引用,下面修改nginx的配置文件:

 

include /consul/nginx-template/*.conf;

 

加上這一句,意思是 引用一下 

/consul/nginx-template/ 下面的所有conf文件的nginx配置信息


下面運行consul-template:

consul-template --consul-addr 192.168.1.23:8500 --template "/consul/nginx-template/nginx.ctmpl:/consul/nginx-template/vhost.conf:service nginx restart" --log-level=info

這句的意思是,將從consul服務數據中讀取 最新的服務發現結果,將有關於 apigateway 的數據,實時地更新到 consul/nginx-template/vhost.conf, 更新的過程用的模板是 /consul/nginx-template/nginx.ctmpl, 更新完之后順便執行了一下 service nginx restart,重啟了nginx服務。

 

執行完之后,我們可以看到 在consul/nginx-template/ 多了一個 vhost.conf文件,里面的內容是 

upstream ocelot {
    
    server 192.168.1.23:8101;
    
    server 192.168.1.23:8102;
    
    server 192.168.1.23:8103;
    
}


server {
        listen       8105;
        location / {
            proxy_pass   http://ocelot ;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection keep-alive;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_cache_bypass $http_upgrade;

        }

  }

確實是我們要內容。

 

下面,把其中一個webapi停掉,

$ supervisorctl
$ stop apigateway3

把第3個網關api停掉了

看會發生什么事?

2019/04/17 07:59:24.954777 [INFO] (runner) initiating run
2019/04/17 07:59:24.958652 [INFO] (runner) rendered "/consul/nginx-template/nginx.ctmpl" => "/consul/nginx-template/vhost.conf"
2019/04/17 07:59:24.958722 [INFO] (runner) executing command "service nginx restart" from "/consul/nginx-template/nginx.ctmpl" => "/consul/nginx-template/vhost.conf"
2019/04/17 07:59:24.958913 [INFO] (child) spawning: service nginx restart

這時consul-template會告訴我們,nginx配置更新的消息,

再打開vhost.conf

upstream ocelot {
    
    server 192.168.1.23:8101;
    
    server 192.168.1.23:8102;
    
}


server {
        listen       8105;
        location / {
            proxy_pass   http://ocelot ;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection keep-alive;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_cache_bypass $http_upgrade;

        }

  }

下游服務節點少了一個,nginx配置確實得到及時的更正。

 

將consul服務開啟加入守護進程,以保證機器重啟能自啟動consul 服務:

 

[program:consul]
command=consul agent -server -ui -bootstrap-expect=1 -data-dir=/tmp/consul -node=consul-1 -client=0.0.0.0 -bind=0.0.0.0 -datacenter=dc1 -config-dir=/consul/testservices
startsecs=10
autostart=true
autorestart=true
stderr_logfile=/var/log/applogs/consul.err.log
stdout_logfile=/var/log/applogs/consul.out.log
user=root
stopsignal=INT

[program:consultemplate]
command=consul-template --consul-addr 192.168.1.23:8500 --template "/consul/nginx-template/nginx.ctmpl:/consul/nginx-template/vhost.conf:service nginx restart" --log-level=info
startsecs=10
autostart=true
autorestart=true
stderr_logfile=/var/log/applogs/consul-template.err.log
stdout_logfile=/var/log/applogs/consul-template.out.log
user=root
stopsignal=INT

 

 

 

上面是在做試驗,但生產環境下:

1.只有一台nginx服務器是不夠的,最好要有兩台nginx服務,通過keepalived配置兩台nginx服務器,一主一從。這樣就避免了如果一台nginx服務器故障了,就沒法做負載均衡。

2.只有一個consul服務是不夠的,官方建議是要有3個node共同組成一個datacenter。這樣就避免了只有一台服務器在提供服務發現的功能。

3. 3個網關應該是部署在3台不同的web 服務器上面。

后面,可能會學習一下如果對2台nginx服務器做keepalive聯盟。關於nginx+keepalive 配置雙機 master/backup 的文章:https://blog.51cto.com/12922638/2155817

 

本文參考文章:https://www.jianshu.com/p/fa41434d444a

最后盜一下里面兩張圖:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM