動(dòng)態(tài)的負(fù)載均衡控制类垫;
平滑上下線服務(wù)培廓,升級(jí)服務(wù);
高可能保證–自動(dòng)踢離線服務(wù)下線荣堰;
具體思路
利用lua中 "lua_shared_dict" 指令開辟一個(gè)共享內(nèi)存空間;
通過API動(dòng)態(tài)根據(jù)key值&參數(shù)修改 upstream (這里使用 host 作為key);
利用 proxy_pass 可使用變量特性及l(fā)ua指令 "set_by_lua" 動(dòng)態(tài)修改當(dāng)前 upstream 變量即可床未;
配置:
worker_processes 1;
pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include 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"';
sendfile on;
keepalive_timeout 65;
#lua_shared_dict upstreams 1m; # 聲明一個(gè)ngx多進(jìn)程全局共享內(nèi)存區(qū)域,_G 作為基于shm的Lua字典的存儲(chǔ)空間ngx.shared.<name>
lua_shared_dict _ups_zone 64m; # 定義upstream共享內(nèi)存空間
upstream backend { # 配置后端服務(wù)器組
server 127.0.0.1:18084;
server 127.0.0.1:18083;
}
server {
listen 8000;
server_name localhost;
access_log logs/80.access.log main;
error_log logs/80.error.log error;
#更新API接口
location = /ups_update {
content_by_lua '
local ups = ngx.req.get_uri_args()["ups"]
if ups == nil then
ngx.say("usage: /ups_update?ups=x.x.x.x")
return
end
local host = ngx.var.http_host
local ups_from = ngx.shared._ups_zone:get(host);
ngx.log(ngx.WARN, host, " update upstream from ", ups_from, " to ", ups)
ngx.shared._ups_zone:set(host, ups);
ngx.say(host, " update upstream from ", ups_from, " to ", ups)
';
}
location / {
# 動(dòng)態(tài)設(shè)置當(dāng)前 upstream, 未設(shè)置則使用默認(rèn) upstream
set_by_lua $cur_ups '
local ups = ngx.shared._ups_zone:get(ngx.var.http_host)
if ups ~= nil then
ngx.log(ngx.ERR, "get [", ups, "] from ngx.shared._ups_zone")
return ups
end
--ngx.log(ngx.INFO, "use default upstream");
return "qq_backend";
'
proxy_next_upstream off;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass $scheme://$cur_ups;
}
}
}
測(cè)試切換upstream的backend效果:
1振坚、默認(rèn)情況【請(qǐng)求4次】:
root@ubuntu:~# curl 127.0.0.1:8000
83 server
root@ubuntu:~# curl 127.0.0.1:8000
84 server
root@ubuntu:~# curl 127.0.0.1:8000
83 server
root@ubuntu:~# curl 127.0.0.1:8000
84 server
切換upstream
root@ubuntu:~# curl 127.0.0.1:8000/ups_update?ups=127.0.0.1:18083
127.0.0.1:8000 update upstream from 127.0.0.1:18083 to 127.0.0.1:18083
root@ubuntu:~# curl 127.0.0.1:8000
83 server
root@ubuntu:~# curl 127.0.0.1:8000
83 server
root@ubuntu:~# curl 127.0.0.1:8000
83 server
root@ubuntu:~# curl 127.0.0.1:8000
83 server
切換upstream:
worker_processes 1;
pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include 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"';
sendfile on;
keepalive_timeout 65;
lua_shared_dict upstreams 1m; # 聲明一個(gè)ngx多進(jìn)程全局共享內(nèi)存區(qū)域,_G 作為基于shm的Lua字典的存儲(chǔ)空間ngx.shared.<name>
upstream default_upstream { # 配置后端服務(wù)器組
server 127.0.0.1:18081;
server 127.0.0.1:18082;
}
upstream lua_upstream { # 配置后端服務(wù)器組
server 127.0.0.1:18084;
server 127.0.0.1:18083;
}
server {
listen 8000;
server_name localhost;
access_log logs/80.access.log main;
error_log logs/80.error.log error;
location = /_switch_upstream {
content_by_lua_block{
local ups = ngx.req.get_uri_args()["upstream"]
if ups == nil or ups == "" then
ngx.say("upstream is nil 1")
return nil
end
local host = ngx.var.http_host
local upstreams = ngx.shared.upstreams
local ups_src = upstreams:get(host)
ngx.say("Current upstream is :",ups_src)
ngx.log(ngx.WARN, host, " change upstream from ", ups_src, " to ", ups)
local succ, err, forcible = upstreams:set(host, ups)
ngx.say(host, " change upstream from ", ups_src, " to ", ups)
}
}
location / {
set_by_lua_block $my_upstream {
local ups = ngx.shared.upstreams:get(ngx.var.http_host)
if ups ~= nil then
ngx.log(ngx.ERR, "get [", ups,"] from ngx.shared")
return ups
end
return "default_upstream"
}
proxy_next_upstream off;
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_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://$my_upstream ;
}
}
}
切換:
curl 127.0.0.1:8000/_switch_upstream?upstream=lua_upstream
curl 127.0.0.1:8000/_switch_upstream?upstream=default_upstream
這里用的還是靜態(tài)文件斋扰,改成tomcat服務(wù)之后也是可以進(jìn)行代理的切換渡八。要是想持久化的話 ,得用到redis传货。