动态upstream

1. 功能描述

upstream动态化功能,支持添加/删除一组upstream,并且可以在添加时指定算法,以及upstream相关指令。

配置动态upstream模块后,可以通过动态API的方式,添加删除upstream,配合upstream api以及动态proxy_pass功能,可以自由的实现upstream的动态配置和自由切换。

2. 依赖模块

动态upstream功能依赖模块和动态共享内存功能:

njet.conf:

load_module  modules/njt_http_dyn_upstream_module.so;

shared_slab_pool_size  100m; 

njet_ctrl.conf

load_module modules/njt_http_dyn_upstream_api_module.so;

3. 配置说明

njet.conf

helper broker modules/njt_helper_broker_module.so conf/mqtt.conf;
helper ctrl modules/njt_helper_ctrl_module.so conf/ctrl.conf;

load_module  modules/njt_http_dyn_upstream_module.so;
   #动态upstream模块
load_module  modules/njt_http_upstream_member_module.so;
   #upstream_api模块

user  root;
worker_processes auto;

cluster_name helper;
node_name node1;

error_log  logs/error.log info;
pid        logs/njet.pid;
events {
    worker_connections  1024;
}

shared_slab_pool_size  100m;  #动态共享内存管理指令,配置大小要大于需要配置的upstream共享内存大小

http {
    dyn_kv_conf conf/iot-work.conf;
    include       mime.types;
    default_type  application/octet-stream;

    access_log  logs/access.log;

    upstream backend1 {
  
         zone backend1 1m;
   
         server 127.0.0.1:5678;
   
      }

        server {
                listen 5555;
                server_name localhost;
  
                location / { 
                        keepalive_timeout 750s;
                        return 200 "5555 ok";
                }
                 location /test {
                  proxy_http_version 1.1;
                  proxy_set_header Connection "";
                  proxy_pass http://backend1;
                }
                location /mirror {
                   internal;
                   set $upstream dyn_backend1;
                   proxy_pass http://$upstream;
                }
        }
  
        server {
  
               listen 5678;
   
               location / {   
  
                    return 200 "5678 ok";
                }
  
  
        }
  

  
     server {

        listen 5999 ssl;
        server_name test.server.com;

        ssl_certificate       certs/ca/rsa.server.cer.pem;
        ssl_certificate_key   certs/ca/rsa.server.key.pem;
        ssl_ciphers     RSA+AES128:RSA+AES256:RSA+3DES:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:EECDH+AES256:EECDH+3DES:!MD5;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_prefer_server_ciphers  on;

        location / {
            charset utf-8;
            default_type text/html;
            return 200 "5999 ssl $request_uri ok";
        }
    }


}

njet_ctrl.conf

load_module modules/njt_http_sendmsg_module.so;
load_module modules/njt_ctrl_config_api_module.so;
load_module modules/njt_http_upstream_api_module.so;  #upstream api模块
load_module modules/njt_doc_module.so;
load_module modules/njt_http_dyn_upstream_api_module.so;  #动态upstream模块
load_module modules/njt_helper_health_check_module.so;
events {
    worker_connections  1024;
}
error_log         logs/error_ctrl.log info;

http {
    dyn_sendmsg_conf  conf/iot-ctrl.conf;
    dyn_kv_conf       conf/ctrl_kv.conf;
    access_log        logs/access_ctrl.log combined;

    include           mime.types;

    server {
        listen       8081;
        keepalive_timeout 0;

        location /api {
             dyn_module_api;

        }
         location /doc {
             doc_api;
         }

  }

}


cluster_name helper;
node_name node1;

ctrl_kv.conf;

topic /ins/ups/#

4. 配置样例

4.1 API说明

添加一个动态upstream:

POST http://ip+port/api/v1/dyn_ups

删除一个动态upstream

PUT http://ip+port/api/v1/dyn_ups

特别提示:添加动态upstream时应配置持久化指令state,未配置情况下reload后会导致server列表丢失。

4.2 添加动态upstream,并使用默认轮询算法。

发送

curl -X 'POST' \
  'http://192.168.40.119:8081/api/v1/dyn_ups' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "add",
  "upstream_name": "dyn_backend1",
  "upstream_body": "zone dyn_backend1 1m"
}'

返回

{
  "code": 0,
  "msg": "success."
}

4.3 添加动态upstream,并配置ip_hash算法。

发送

curl -X 'POST' \
  'http://192.168.40.119:8081/api/v1/dyn_ups' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "add",
  "upstream_name": "dyn_backend1",
  "upstream_body": "zone dyn_backend1 1m;ip_hash"
}'

返回

{
  "code": 0,
  "msg": "success."
}

4.4 添加动态upstream,并配置keepalive指令。

发送

curl -X 'POST' \
  'http://192.168.40.119:8081/api/v1/dyn_ups' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "add",
  "upstream_name": "dyn_backend1",
  "upstream_body": "zone dyn_backend1 1m;keepalive 10;"
}'

返回

{
  "code": 0,
  "msg": "success."
}

4.5 添加动态upstream,并配置持久化指令。

发送

curl -X 'POST' \
  'http://192.168.40.119:8081/api/v1/dyn_ups' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "add",
  "upstream_name": "dyn_backend1",
  "upstream_body": "zone dyn_backend1 1m;state upstream.conf;"
}'

返回

{
  "code": 0,
  "msg": "success."
}

4.6 查询当前配置的所有upstream

发送

curl -X 'GET' \
  'http://192.168.40.119:8081/api/v1/config/dyn_upstream' \
  -H 'accept: application/json'

返回

[
  {
    "name": "backend1",
    "balance": "round_robin",
    "zone": "backend1",
    "is_static": true
  }  {
    "name": "dyn_backend1",
    "balance": "round_robin",
    "zone": "dyn_backend1",
    "is_static": false
  }
]

4.7 删除当前配置的动态upstream

发送

curl -X 'PUT' \
  'http://192.168.40.119:8081/api/v1/dyn_ups' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "del",
  "upstream_name": "dyn_backend1"
}'

返回

{
  "code": 0,
  "msg": "success."
}

4.8 在动态upstream中添加一个server

先添加一组动态upstream

curl -X 'POST' \
  'http://192.168.40.119:8081/api/v1/dyn_ups' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "add",
  "upstream_name": "dyn_backend1",
  "upstream_body": "zone dyn_backend1 1m;state upstream.conf;"
}'

返回值

{
  "code": 0,
  "msg": "success."
}

使用动态upstream api添加一个server

curl -X 'POST' \
  'http://192.168.40.119:8081/api/v1/upstream_api/http/upstreams/dyn_backend1/servers/' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "server": "127.0.0.1:5678",
  "weight": 4,
  "max_conns": 0,
  "max_fails": 0,
  "fail_timeout": "10s",
  "slow_start": "10s",
  "route": "",
  "backup": false,
  "down": false
}'

返回值

{
  "id": 0,
  "server": "127.0.0.1:5678",
  "weight": 4,
  "max_conns": 0,
  "max_fails": 0,
  "fail_timeout": "10s",
  "slow_start": "10s",
  "route": "",
  "backup": false,
  "down": false
}

4.9 在动态upstream中添加一个server,并使用动态proxy_pass更新location的proxy_pass

先添加一组动态upstream

curl -X 'POST' \
  'http://192.168.40.119:8081/api/v1/dyn_ups' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "add",
  "upstream_name": "dyn_backend1",
  "upstream_body": "zone dyn_backend1 1m;state upstream.conf;"
}'

返回值

{
  "code": 0,
  "msg": "success."
}

使用动态upstream api添加一个server

curl -X 'POST' \
  'http://192.168.40.119:8081/api/v1/upstream_api/http/upstreams/dyn_backend1/servers/' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "server": "127.0.0.1:5678",
  "weight": 4,
  "max_conns": 0,
  "max_fails": 0,
  "fail_timeout": "10s",
  "slow_start": "10s",
  "route": "",
  "backup": false,
  "down": false
}'

返回值

{
  "id": 0,
  "server": "127.0.0.1:5678",
  "weight": 4,
  "max_conns": 0,
  "max_fails": 0,
  "fail_timeout": "10s",
  "slow_start": "10s",
  "route": "",
  "backup": false,
  "down": false
}

使用动态proxy_pass接口切换upstream

curl -X 'PUT' \
  'http://192.168.40.119:8081/api/v1/config/proxy_pass' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '{
  "servers": [
    {
      "listens": [
        "0.0.0.0:5555"
      ],
      "serverNames": [
        "localhost"
      ],
      "locations": [
        {
          "location": "/test",
          "proxy_pass": "http://dyn_backend1"
        }
      ]
    }
  ]
}'

返回

{
  "code": 0,
  "msg": "success."
}

使用proxy_pass查询接口查看当前location的proxy_pass

发送

curl -X 'GET' \
  'http://192.168.40.119:8081/api/v1/config/proxy_pass' \
  -H 'accept: application/json'

返回

{
  "servers": [
    {
      "listens": [
        "0.0.0.0:5555"
      ],
      "serverNames": [
        "localhost"
      ],
      "locations": [
        {
          "location": "/test",
          "proxy_pass": "http://dyn_backend1"
        }
      ]
    }
  ]
}