幾個月沒有更新部落格了,已經長草了,特意來除草。之前基于nginx反向代理使用的是:nginx + confd + etcd的存儲方式,最近發現部門DBA同僚使用consul + redis + 哨兵實作的主從自動選舉切換,不影響業務的方式,還有看到有些公司分享的consul + mha的方式,覺得不錯,于是研究了下consul,本案例是基于consul + consul-template + nginx + flask + mysql構成的。既然consul這麼傳神,我們先來看看consul是什麼:
consul是HashiCorp公司(曾經開發過vgrant) 推出的一款開源工具, 基于go語言開發, 輕量級, 用于實作分布式系統的服務發現與配置。 與其他類似産品相比, 提供更“一站式”的解決方案。 consul内置有KV存儲, 服務注冊/發現, 健康檢查, HTTP+DNS API, Web UI等多種功能。官網: https://www.consul.io/其他同類服務發現與配置的主流開源産品有:zookeeper和ETCD。
consul的優勢:
1. 支援多資料中心, 内外網的服務采用不同的端口進行監聽。 多資料中心叢集可以避免單資料中心的單點故障, zookeeper和 etcd 均不提供多資料中心功能的支援
2. 支援健康檢查. etcd 不提供此功能.
3. 支援 http 和 dns 協定接口. zookeeper 的內建較為複雜,etcd 隻支援 http 協定. 有DNS功能, 支援REST API
4. 官方提供web管理界面, etcd 無此功能.
5. 部署簡單, 運維友好, go二進制檔案解壓即用。批量部署友善
Consul和其他服務發現工具的對比表:
主要架構: 架構說明:- Consul Cluster由部署和運作了Consul Agent的節點組成。 在Cluster中有兩種角色:Server和 Client。
- Server和Client的角色和Consul Cluster上運作的應用服務無關, 是基于Consul層面的一種角色劃分.
- Consul Server: 用于維護Consul Cluster的狀态資訊, 實作資料一緻性, 響應RPC請求。官方建議是: 至少要運作3個或者3個以上的Consul Server。 多個server之中需要選舉一個leader, 這個選舉過程Consul基于Raft協定實作. 多個Server節點上的Consul資料資訊保持強一緻性。 在區域網路内與本地用戶端通訊,通過廣域網與其他資料中心通訊。Consul Client: 隻維護自身的狀态, 并将HTTP和DNS接口請求轉發給服務端。
- Consul 支援多資料中心, 多個資料中心要求每個資料中心都要安裝一組Consul cluster,多個資料中心間基于gossip protocol協定來通訊, 使用Raft算法實作一緻性
基礎介紹到這裡,下面直接進入我們主題,環境介紹(生産環境建議建構consul server的叢集):
consul:192.168.113.174
nginx:192.168.113.174
反向代理伺服器:
192.168.113.175:8080
192.168.113.176:8080
1、consul 與consul-template安裝:
安裝非常容易,到官方https://www.consul.io/downloads.html下載下傳相關包,解壓之後放到/usr/local/bin/ 目錄下即可。
2、啟動一下consul server:
[root@master ~]# consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -bind 0.0.0.0 -client 0.0.0.0 -ui
##然後我們打開一下web:192.168.113.174:8500界面,即可看到相關的服務注冊資訊:
3、下面我們準備一下consul模闆,然後再注冊服務。
[root@master ~]# cat item.consul.ctmpl
{{range services}} {{$name := .Name}} {{$service := service .Name}}
upstream {{$name}} {
zone upstream-{{$name}} 64k;
{{range $service}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;
{{else}}server 127.0.0.1:65535; # force a 502{{end}}
} {{end}}
{{range services}} {{$name := .Name}}
server {
listen 80;
server_name www.{{$name}}.com;
index index.html index.htm index.php;
## send request back to apache ##
location / {
proxy_pass http://{{$name}};
#Proxy Settings
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_max_temp_file_size 0;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
}
{{end}}
4、觀察一下nginx的配置資訊,首先我們确認下配置檔案自目錄下沒有資訊:
[root@master conf.d]# pwd
/etc/nginx/conf.d
[root@master conf.d]# ls
5、啟動模闆檔案:
[root@master ~]# consul-template -consul 127.0.0.1:8500 -template item.consul.ctmpl:default.conf:"/usr/sbin/nginx -s reload"
##根據注冊資訊與模闆生成一個default.conf的檔案,具體文法可以檢視相關模闆文檔:
[root@master ~]# consul-template -consul 127.0.0.1:8500 -template item.consul.ctmpl:/etc/nginx/conf.d/default.conf:"/usr/sbin/nginx -s reload"
6、往裡面注冊服務資訊:
[root@master conf.d]# curl -X PUT http://127.0.0.1:8500/v1/catalog/register -d'{"Datacenter": "dc1", "Node":"tomcat1", "Address":"192.168.113.175","Service": {"Id" :"192.168.113.175:8080", "Service": "tomcat","tags": ["dev"], "Port": 8080}}'
[root@master conf.d]# curl -X PUT http://127.0.0.1:8500/v1/catalog/register -d'{"Datacenter": "dc1", "Node":"tomcat2", "Address":"192.168.113.176","Service": {"Id" :"192.168.113.176:8080", "Service": "tomcat","tags": ["dev"], "Port": 8080}}'
7、web界面我們檢視一下是否已經注冊了服務:
8、看一下配置檔案是否已經生成:
upstream tomcat {
zone upstream-tomcat 64k;
server 192.168.113.175:8080 max_fails=3 fail_timeout=60 weight=1;
server 192.168.113.176:8080 max_fails=3 fail_timeout=60 weight=1;
}
server {
listen 80;
server_name www.consul.com;
index index.html index.htm index.php;
## send request back to apache ##
location / {
proxy_pass http://consul;
#Proxy Settings
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_max_temp_file_size 0;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
}
server {
listen 80;
server_name www.tomcat.com;
index index.html index.htm index.php;
## send request back to apache ##
location / {
proxy_pass http://tomcat;
#Proxy Settings
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_max_temp_file_size 0;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
}
9、到這一步似乎已經完成了,不過像這種東西能不能平台話呢,看一下我建構的平台添加虛拟主機部分:
10、添加後端轉發位址:
11、下面我們把添加的後端位址同步到consul,然後檢視一下域名的變化:
12、看一下web ui我們會發現已經添加了一個域名:
13、再看一下nginx的配置檔案: