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: