from http://blog.csdn.net/force_eagle/article/details/51966333
具体思路是:
1 > 利用lua中 "lua_shared_dict" 指令开辟一个共享内存空间;
2> 通过API动态根据key值&参数修改 upstream (这里使用 host 作为key);
3> 利用 proxy_pass 可使用变量特性及lua指令 "set_by_lua" 动态修改当前 upstream 变量即可;
以下是利用 qq.com 作为示例:
- http {
- lua_shared_dict _ups_zone 64m; # 定义upstream共享内存空间
- ...
- upstream qq_backend{
- server 14.17.42.40;
- server 14.17.32.211;
- server 59.37.96.63;
- }
- server {
- listen 80;
- server_name www.qq.com *.qq.com;
- access_log off;
- # 更新 upstream 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 / {
- # 动态设置当前 upstream, 未设置则使用默认 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;
- }
- }
- }
- cur -x 127.0.0.1:80 www.qq.com # 使用默认upstream
- # 修改为140.206.160.207 & 61.135.157.156
- curl -x 127.0.0.1:80 www.qq.com/ups_update?ups=140.206.160.207
- curl -x 127.0.0.1:80 www.qq.com/ups_update?ups=61.135.157.156
这里只是一个简单的思路,并未考虑到 upstream 持久化,如需要可参考以下这篇文章, 使用 Redis 来实现: