《基于Upsync模塊實(shí)現(xiàn)Nginx動(dòng)態(tài)配置》要點(diǎn):
本文介紹了基于Upsync模塊實(shí)現(xiàn)Nginx動(dòng)態(tài)配置,希望對(duì)您有用。如果有疑問(wèn),可以聯(lián)系我們。
題圖:By Federico Respini From Unsplash
Upsync是新浪微博開(kāi)源的基于Nginx實(shí)現(xiàn)動(dòng)態(tài)配置的三方模塊.Nginx-Upsync-Module
的功能是拉取Consul的后端server的列表,并動(dòng)態(tài)更新Nginx的路由信息.此模塊不依賴于任何第三方模塊.Consul作為Nginx的DB,利用Consul的KV服務(wù),每個(gè)Nginx Work進(jìn)程獨(dú)立的去拉取各個(gè)upstream的配置,并更新各自的路由.
在Nginx的設(shè)計(jì)中,每一個(gè)upstream維護(hù)了一張靜態(tài)路由表,存儲(chǔ)了backend的ip、port以及其他的meta信息.每次請(qǐng)求到達(dá)后,會(huì)依據(jù)location檢索路由表,然后依據(jù)具體的調(diào)度算法(如round robin )選擇一個(gè)backend轉(zhuǎn)發(fā)請(qǐng)求.但這張路由表是靜態(tài)的,如果變更后,則必須reload,經(jīng)常reload的話這對(duì)SLA有較大影響.
為了達(dá)到減少reload的目的,大多通過(guò)動(dòng)態(tài)更新維護(hù)路由表來(lái)解決這個(gè)問(wèn)題.通常路由表的維護(hù)有Push與Pull兩種方式.
通過(guò)Nginx API向Nginx發(fā)出請(qǐng)求,操作簡(jiǎn)單、便利.
架構(gòu)圖如下:
http api除了操作簡(jiǎn)單、方便,而且實(shí)時(shí)性好;缺點(diǎn)是有多臺(tái)Nginx時(shí),不同Nginx路由表的一致性難于保證,如果某一條注冊(cè)失敗,便會(huì)造成服務(wù)配置的不一致,容錯(cuò)復(fù)雜.另外擴(kuò)容Nginx服務(wù)器,需要從其他的Nginx中同步路由表.
路由表中所有的backend信息(含meta)存儲(chǔ)到Consul,所有的Nginx從Consul拉取相關(guān)信息.有變更則更新路由表,利用Consul解決一致性問(wèn)題,同時(shí)利用Consul的wait機(jī)制解決實(shí)時(shí)性問(wèn)題.利用Consul的index進(jìn)行增量摘取,解決帶寬占用問(wèn)題.
在Consul中,一個(gè)K/V對(duì)代表一個(gè)backend信息,增加一個(gè)即視作擴(kuò)容,減少一個(gè)即為縮容.調(diào)整meta信息,如權(quán)重,也可以達(dá)到動(dòng)態(tài)流量調(diào)整的目的.
架構(gòu)圖如下:
Upsync模塊使用了第二種模式,通過(guò)拉取Consul的后端Server的列表,并動(dòng)態(tài)更新Nginx的路由信息.Upsync模塊工作流程圖如下:
每個(gè)Work進(jìn)程定時(shí)的去Consul拉取相應(yīng)upstream的配置,若Consul發(fā)現(xiàn)對(duì)應(yīng)upstream的值沒(méi)有變化,便會(huì)hang住這個(gè)請(qǐng)求五分鐘(默認(rèn)值).在這五分鐘內(nèi)對(duì)此upstream的任何操作,都會(huì)立刻返回給Nginx對(duì)相應(yīng)路由進(jìn)行更新.
upstream變更后,除了更新Nginx的緩存路由信息,還會(huì)把本upstream的后端server列表dump到本地,保持本地server信息與consul的一致性.
除了注冊(cè)/注銷(xiāo)后端的server到consul,會(huì)更新到Nginx的upstream路由信息外,對(duì)后端server屬性的修改也會(huì)同步到nginx的upstream路由.
Upsync模塊支持修改的屬性有:weight、max_fails、fail_timeout、down.
每個(gè)work進(jìn)程各自拉取、更新各自的路由表,采用這種方式的原因:
Upsync模塊高可用性
Nginx的后端列表更新依賴于Consul,但是不強(qiáng)依賴于它,具體表現(xiàn)為:
Nginx啟動(dòng)流程圖如下:
Nginx啟動(dòng)時(shí),master進(jìn)程首先會(huì)解析本地的配置文件,解析完成功,接著進(jìn)行一系列的初始化,之后便會(huì)開(kāi)始work進(jìn)程的初始化.work初始化時(shí)會(huì)去Consul拉取配置,進(jìn)行work進(jìn)程upstream路由信息的更新,若拉取成功,便直接更新,若拉取失敗,便會(huì)打開(kāi)配置的dump后端列表的文件,提取之前dump下來(lái)的server信息,進(jìn)行upstream路由的更新,之后便開(kāi)始正常的提供服務(wù).
每次去拉取Consul都會(huì)設(shè)置連接超時(shí),由于Consul在無(wú)更新的情況下默認(rèn)會(huì)hang五分鐘,所以響應(yīng)超時(shí)配置時(shí)間應(yīng)大于五分鐘.大于五分鐘之后,Consul依舊沒(méi)有返回,便直接做超時(shí)處理.
Consul是HashiCorp公司推出的開(kāi)源工具,用于實(shí)現(xiàn)分布式系統(tǒng)的服務(wù)發(fā)現(xiàn)與配置.
Upsync最新版本是支持ectd,這里用ectd做為后端存儲(chǔ).有關(guān)consule的講解后面單獨(dú)來(lái)講.如果你還沒(méi)有etcd環(huán)境,可參考「etcd使用入門(mén)」一文搭建一個(gè).
這里使用的是Upsync最新版本,目前支持Nginx 1.9+.nginx-upstream-check-module
是Tengine中的模塊,主要用于upstream的健康檢查.由于nginx-upstream-check-module
最新版本只支持1.9.2,所以這里Nginx選用1.9.2.
$ cd /root
$ wget ‘http://nginx.org/download/nginx-1.9.2.tar.gz’
$ git clone https://github.com/weibocom/nginx-upsync-module
$ git clone https://github.com/xiaokai-wang/nginx_upstream_check_module
$ apt-get install libreadline-dev libncurses5-dev libpcre3-dev libssl-dev perl make build-essential
$ tar xzvf nginx-1.9.2.tar.gz
$ cd nginx-1.9.2
$ patch -p0 < ~/nginx_upstream_check_module/check_1.9.2+.patch
$ ./configure –add-module=/root/nginx_upstream_check_module –add-module=/root/nginx-upsync-module
$ make && make install
Nginx會(huì)默認(rèn)安裝到/usr/local/nginx
目錄下.
創(chuàng)建用戶和相應(yīng)目錄
$ useradd -M nginx -s /sbin/nologin
$ mkdir -p /var/log/nginx
$ chown -R nginx.nginx /var/log/nginx
$ mkdir /usr/local/nginx/conf/conf.d
$ mkdir -p /usr/local/nginx/conf/servers
修改Nginx主配置文件
# 備份原配置文件 $ cd /usr/local/nginx $ mv conf/nginx.conf conf/nginx.conf.bak # 修改配置 $ vim /usr/local/nginx/conf/nginx.conf user ?nginx; worker_processes ?5; error_log ?/var/log/nginx/error.log warn; pid ? ? ? ?/var/run/nginx.pid; events { ? ?worker_connections ?1024; } http { ? ?include ? ? ? /usr/local/nginx/conf/mime.types; ? ?default_type ?application/octet-stream; ? ?log_format ?main ?‘$remote_addr – $remote_user [$time_local] “$request” ‘ ? ? ? ? ? ? ? ? ? ? ?‘$status $body_bytes_sent “$http_referer” ‘ ? ? ? ? ? ? ? ? ? ? ?‘”$http_user_agent” “$http_x_forwarded_for”‘; ? ?access_log ?/var/log/nginx/access.log ?main; ? ?sendfile ? ? ? ?on; ? ?#tcp_nopush ? ? on; ? ?keepalive_timeout ?65; ? ?#gzip ?on; ? ?include /usr/local/nginx/conf/conf.d/*.conf; }
創(chuàng)建站點(diǎn)配置文件
$ vim /usr/local/nginx/conf/conf.d/site.conf upstream test { ?# fake server otherwise ngx_http_upstream will report error when startup ?server 127.0.0.1:11111; ?# all backend server will pull from consul when startup and will delete fake server ?# 后端使用consul存儲(chǔ) ?# upsync 192.168.2.210:8500/v1/kv/upstreams/test upsync_timeout=6m upsync_interval=500ms upsync_type=consul strong_dependency=off; ?# 后端使用etcd存儲(chǔ) ?upsync 192.168.2.210:2379/v2/keys/upstreams/test upsync_timeout=6m ?upsync_interval=500ms upsync_type=etcd strong_dependency=off; ?upsync_dump_path /usr/local/nginx/conf/servers/servers_test.conf; ?#配置健康檢查 ?check interval=1000 rise=2 fall=2 timeout=3000 type=http default_down=false; ?check_http_send “HEAD / HTTP/1.0\r\n\r\n”; ?check_http_expect_alive http_2xx http_3xx; } upstream bar { ?server 192.168.2.210:8080 weight=1 fail_timeout=10 max_fails=3; } server { ?listen 80; ?location = / { ? ?proxy_pass http://test; ?} ?location = /bar { ? ? ?proxy_pass http://bar; ?} ?location = /upstream_show { ? ?upstream_show; ?} ?location = /upstream_status { ? ?check_status; ? ?access_log off; ?} }
$ vi /lib/systemd/system/nginx.service [Unit] Description=The NGINX HTTP and reverse proxy server Documentation=http://nginx.org/en/docs/ After=syslog.target network.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile=/var/run/nginx.pid ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s QUIT $MAINPID PrivateTmp=true [Install] WantedBy=multi-user.target
修改權(quán)限及加入開(kāi)機(jī)啟動(dòng)
$ sudo chmod +x /lib/systemd/system/nginx.service
$ sudo systemctl enable nginx.service
現(xiàn)在可以使用下面的指令來(lái)管理Nginx服務(wù).
$ systemctl start nginx.service
$ systemctl reload nginx.service
$ systemctl restart nginx.service
$ systemctl stop nginx.service
$ systemctl start nginx.service
驗(yàn)證Nginx服務(wù)是否正常
$ systemctl status ?nginx.service ● nginx.service – The NGINX HTTP and reverse proxy server ? Loaded: loaded (/lib/systemd/system/nginx.service; disabled; vendor preset: enabled) ? Active: active (running) since Mon 2017-05-08 10:58:06 CST; 1min 6s ago ? ? Docs: http://nginx.org/en/docs/ ?Process: 22966 ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf (code=exited, status=0/SUCCESS) ?Process: 22963 ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf (code=exited, status=0/SUCCESS) Main PID: 22971 (nginx) ? ?Tasks: 6 ? Memory: 24.5M ? ? ?CPU: 517ms ? CGroup: /system.slice/nginx.service ? ? ? ? ? ├─22971 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.con ? ? ? ? ? ├─22972 nginx: worker process ? ? ? ? ? ├─22973 nginx: worker process ? ? ? ? ? ├─22974 nginx: worker process ? ? ? ? ? ├─22975 nginx: worker process ? ? ? ? ? └─22976 nginx: worker process May 08 10:58:06 dev-master-01 systemd[1]: Starting The NGINX HTTP and reverse proxy server… May 08 10:58:06 dev-master-01 nginx[22963]: nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok May 08 10:58:06 dev-master-01 nginx[22963]: nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful May 08 10:58:06 dev-master-01 systemd[1]: Started The NGINX HTTP and reverse proxy server.
如果要單獨(dú)查看Nginx服務(wù)日志,可以使用以下命令:
$ journalctl -f -u nginx.service
這里在Nginx默認(rèn)站點(diǎn)目錄,用Python啟動(dòng)一個(gè)SimpleHTTPServer進(jìn)行驗(yàn)證.
$ cd /usr/local/nginx/html
$ python -m SimpleHTTPServer 8080
增加一個(gè)后端服務(wù)器
$ curl -X PUT http://192.168.2.210:2379/v2/keys/upstreams/test/192.168.2.210:8080
其它Upstream模塊中其它屬性的默認(rèn)值為:weight=1 max_fails=2 fail_timeout=10 down=0 backup=0;
.如果你要調(diào)整這些值,可以用以下命令格式進(jìn)行提交:
$ curl -X PUT -d value=”{\”weight\”:1, \”max_fails\”:2, \”fail_timeout\”:10}” http://
$etcd_ip:$port/v2/keys/$dir1/$upstream_name/$backend_ip:$backend_port
刪除一個(gè)后端服務(wù)器
$ curl -X DELETE http://192.168.2.210:2379/v2/keys/upstreams/test/192.168.2.210:8080
增加一個(gè)后端服務(wù)器
$ curl -X PUT http://192.168.2.210:8500/v1/kv/upstreams/test/192.168.2.210:8080
刪除一個(gè)后端服務(wù)器
$ curl -X DELETE http://192.168.2.210:8500/v1/kv/upstreams/test/192.168.2.210:8080
頁(yè)面自動(dòng)根據(jù)proxy_pass http://test;
成功轉(zhuǎn)到了后端服務(wù)器.
$ cat /usr/local/nginx/conf/servers/servers_test.conf server 192.168.2.210:8080 weight=1 max_fails=2 fail_timeout=10s;
文章來(lái)自微信公眾號(hào):運(yùn)維之美
轉(zhuǎn)載請(qǐng)注明本頁(yè)網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/4156.html