nginx动态负载upstream三种方案
by ronin47
项目背景:
链路流程: vip —>nginx—>upstream—>server—>ip+port
1.目前还没做路由功能,分组是按服务器分组(不是按用户分组),分组发布过程一个队列形式,这里提供自定义规则切换服upstrem。
2.不管是全量发布,分组发布,快速发布,lb只做一件事:切换upstream(running_upstream与standy_upstream
3.动态切换LB,做法两种,一是直接操作upstream,二是操作upstream里的server.
4.与ci集成方式:超链接web
方案一:模块fly操作upstream,web方式增删查改upsterem里的server
无drop重启nginx
kill -HUP `cat /data/nginx/logs/nginx.pid` #!/bin/sh BASE_DIR='/usr/local/' ${BASE_DIR}nginx/sbin/nginx -t -c ${BASE_DIR}nginx/conf/nginx.conf >& ${BASE_DIR}nginx/logs/nginx.start info=`cat ${BASE_DIR}nginx/logs/nginx.start` if [ `echo $info | grep -c "syntax is ok" ` -eq 1 ]; then if [ `ps aux|grep "nginx"|grep -c "master"` == 1 ]; then kill -HUP `cat ${BASE_DIR}nginx/logs/nginx.pid` echo "ok" else killall -9 nginx sleep 1 ${BASE_DIR}nginx/sbin/nginx fi else echo "######## error: ########" cat ${BASE_DIR}nginx/logs/nginx.start fi
reference:
方案二:模块ngx_dynamic_upstream,api+python方式(直接操作upstream里的server)
因为api接口操作不是太直观,在django上以web方式增删查改upstream
HTTP APIsYou can operate upstreams dynamically with HTTP APIs.list$ curl "http://127.0.0.1:6000/dynamic?upstream=zone_for_backends"server 127.0.0.1:6001;server 127.0.0.1:6002;server 127.0.0.1:6003;$
verbose$ curl "http://127.0.0.1:6000/dynamic?upstream=zone_for_backends&verbose="server 127.0.0.1:6001 weight=1 max_fails=1 fail_timeout=10;server 127.0.0.1:6002 weight=1 max_fails=1 fail_timeout=10;server 127.0.0.1:6003 weight=1 max_fails=1 fail_timeout=10;$update_parameters$ curl "http://127.0.0.1:6000/dynamic?upstream=zone_for_backends&server=127.0.0.1:6003&weight=10&max_fails=5&fail_timeout=5"server 127.0.0.1:6001 weight=1 max_fails=1 fail_timeout=10;server 127.0.0.1:6002 weight=1 max_fails=1 fail_timeout=10;server 127.0.0.1:6003 weight=10 max_fails=5 fail_timeout=5;$The supported parameters are blow.weightmax_failsfail_timeoutdown$ curl "http://127.0.0.1:6000/dynamic?upstream=zone_for_backends&server=127.0.0.1:6003&down="server 127.0.0.1:6001 weight=1 max_fails=1 fail_timeout=10;server 127.0.0.1:6002 weight=1 max_fails=1 fail_timeout=10;server 127.0.0.1:6003 weight=1 max_fails=1 fail_timeout=10 down;$up$ curl "http://127.0.0.1:6000/dynamic?upstream=zone_for_backends&server=127.0.0.1:6003&up="server 127.0.0.1:6001 weight=1 max_fails=1 fail_timeout=10;server 127.0.0.1:6002 weight=1 max_fails=1 fail_timeout=10;server 127.0.0.1:6003 weight=1 max_fails=1 fail_timeout=10;$add$ curl "http://127.0.0.1:6000/dynamic?upstream=zone_for_backends&add=&server=127.0.0.1:6004"server 127.0.0.1:6001;server 127.0.0.1:6002;server 127.0.0.1:6003;server 127.0.0.1:6004;$remove$ curl "http://127.0.0.1:6000/dynamic?upstream=zone_for_backends&remove=&server=127.0.0.1:6003"server 127.0.0.1:6001;server 127.0.0.1:6002;server 127.0.0.1:6004;
reference:
方案三:lua(lua_code_cache)热装载+upstream ,直接操作upstream
简说热装载(热加载) :lua代码产生变更,利用lua_code_cache on ,实现自动加载,不用reload nginx。 亮点: 通过lua处理,不用重启nginx,利用api进行增删查改 不足:操作还是基于命令方式,后期还得加上web操作
restful interface
GET
/detail get all upstreams and their servers/list get the list of upstreams/upstream/name find the upstream by it's name
POST
/upstream/name update one upstreambody commands;body server ip:port;
DELETE
/upstream/name delete one upstreamCall the interface, when you get the return code is HTTP_INTERNAL_SERVER_ERROR 500, you need to reload nginx to make the Nginx work at a good state.If you got HTTP_CONFLICT 409, you need resend the same commands again latter.The /list and /detail interface will return HTTP_NO_CONTENT 204 when there is no upstream.Other code means you should modify your commands and call the interface again.ATTENEION: You also need a third-party to generate the new config and dump it to Nginx'conf directory.
Sample» curl -H "host: dyhost" 127.0.0.1:8080502 Bad Gateway 502 Bad Gateway
nginx/1.3.13 » curl -d "server 127.0.0.1:8089;server 127.0.0.1:8088;" 127.0.0.1:8081/upstream/dyhostsuccess» curl -H "host: dyhost" 127.0.0.1:80808089» curl -H "host: dyhost" 127.0.0.1:80808088» curl 127.0.0.1:8081/detailhost1server 127.0.0.1:8088host2server 127.0.0.1:8089dyhostserver 127.0.0.1:8089server 127.0.0.1:8088» curl -i -X DELETE 127.0.0.1:8081/upstream/dyhostsuccess» curl 127.0.0.1:8081/detailhost1server 127.0.0.1:8088host2server 127.0.0.1:8089
API
extern ngx_flag_t ngx_http_dyups_api_enable;ngx_int_t ngx_dyups_update_upstream(ngx_str_t *name, ngx_buf_t *buf, ngx_str_t *rv);ngx_int_t ngx_dyups_delete_upstream(ngx_str_t *name, ngx_str_t *rv);extern ngx_dyups_add_upstream_filter_pt ngx_dyups_add_upstream_top_filter;extern ngx_dyups_del_upstream_filter_pt ngx_dyups_del_upstream_top_filter;
NOTICE: you should add the directive dyups_interface into your config file to active this feature
content_by_lua ' local dyups = require "ngx.dyups" local status, rv = dyups.update("test", [[server 127.0.0.1:8088;]]); ngx.print(status, rv) if status ~= ngx.HTTP_OK then ngx.print(status, rv) return end ngx.print("update success") status, rv = dyups.delete("test") if status ~= ngx.HTTP_OK then ngx.print(status, rv) return end ngx.print("delete success")';
reference:
https://github.com/yzprofile/ngx_http_dyups_module https://github.com/moonbingbing/openresty-best-practices/blob/master/ngx_lua/hot_load.md
demo site: