Openresty学习使用(三)发版脚本

Openresty学习使用(三)发版脚本

    • 说明
    • 脚本代码
      • lua-upstream-nginx-module相关
      • lua-resty-upstream-healthcheck相关
      • 发版脚本

说明

本文是利用上篇文章中介绍的两个openresty的插件来实现发版。
插件如下:
lua-resty-upstream-healthcheck
lua-upstream-nginx-module

OpenResty 1.9.3.2以及之后的版本,都已经内置了这两个插件,所以直接使用就好。

脚本代码

lua-upstream-nginx-module相关

nginx配置

location /upstreams {
           default_type text/plain;
           content_by_lua_file /usr/local/openresty/nginx/lua/upstream.lua;
        }

lua脚本

local cjson = require "cjson"
local hc = require "resty.upstream.healthcheck"
local concat = table.concat
local upstream = require "ngx.upstream"
local get_servers = upstream.get_servers
local get_upstreams = upstream.get_upstreams
local get_primary_peers = upstream.get_primary_peers
local get_backup_peers = upstream.get_backup_peers
local set_peer_down = upstream.set_peer_down

function string:split(sep)
    local sep, fields = sep or ":", {}
    local pattern = string.format("([^%s]+)", sep)
    self:gsub(pattern, function (c) fields[#fields + 1] = c end)
    return fields
end

local function get_all_upstream()
    local us = get_upstreams()
    local upstreams = {}
    for _, u in ipairs(us) do
        local srvs = get_servers(u)
        upstreams[u] = srvs
    end
    return upstreams
end

local function get_all_peers(upstream_name)
    local primary_peers = get_primary_peers(upstream_name)
    local backup_peers = get_backup_peers(upstream_name)
    local primary_cnt = table.getn(primary_peers)
    local backup_cnt = table.getn(backup_peers)
    local total = table.getn(primary_peers) + table.getn(backup_peers)
    local all_peers = {}
    for i = primary_cnt + 1, total do
        backup_peers[i - primary_cnt]["backup"] = true
        table.insert(primary_peers, i, backup_peers[i - primary_cnt])
    end
    return primary_peers
end

local function op_server(upstream_name, server_name, op)
    local all_peers = get_all_peers(upstream_name)
    for i, peer in ipairs(all_peers) do
        if peer["name"] == server_name then
            target_peer = peer
            break
        end
    end
    if target_peer == nil then
        ngx.say(cjson.encode({code = "E00001", msg = "error peer name"}))
    else
        if op == "down" then
            down_value = true
        else
            down_value = false
        end
        local is_back_up = target_peer["backup"] or false
        set_peer_down(upstream_name, is_back_up, target_peer["id"], down_value)
        ngx.say(cjson.encode({code = "A00000", msg = "Success"}))
    end
end

local http_method = ngx.req.get_method()
local sub_uris = ngx.var.uri:split("/")

if table.getn(sub_uris) == 4 then
    op_server(sub_uris[2], sub_uris[3], sub_uris[4])
end
if table.getn(sub_uris) == 3 then
    if sub_uris[3] == "primary" then
        ngx.say(cjson.encode(get_primary_peers(sub_uris[2])))
    else
        ngx.say(cjson.encode(get_backup_peers(sub_uris[2])))
    end
    ngx.exit(ngx.HTTP_OK)
end
if sub_uris[2] then
    ngx.say(cjson.encode(get_all_peers(sub_uris[2])))
else
    ngx.say(cjson.encode(get_all_upstream()))
end
路径 说明
/upstreams 获取所有的信息
/upstreams/{upstream_name} 根据名称获取信息
/upstreams/{upstream_name}/{server_name} 根据名称和服务获取
/upstreams/{upstream_name}/{server_name}/down 下线
/upstreams/{upstream_name}/{server_name}/up 上线

lua-resty-upstream-healthcheck相关

nginx配置

## 指定共享内存
lua_shared_dict healthcheck 1m;
lua_socket_log_errors off;
## 在worker初始化过程中,启动定时器,进行后端结点的检查
init_worker_by_lua_block {
   local hc = require "resty.upstream.healthcheck"
   local ok, err = hc.spawn_checker {
       -- shm 表示共享内存区的名称,
       shm = "healthcheck",
       -- type 表示健康检查的类型, HTTP or TCP (目前只支持http)
       type = "http",    
       -- upstream 指定 upstream 配置的名称   
       upstream = "api", 
       -- 如果是http类型,指定健康检查发送的请求的URL
       http_req = "GET /api/health HTTP/1.0",
       -- 请求间隔时间,默认是 1 秒。最小值为 2毫秒
       interval = 2000,
       -- 请求的超时时间。 默认值为:1000 毫秒
       timeout = 5000,
       -- 失败多少次后,将节点标记为down。 默认值为 5
       fall = 3, 
       -- 成功多少次后,将节点标记为up。默认值为 2
       rise = 2,
       -- 返回的http状态码,表示应用正常
       valid_statuses = {200, 302},
       -- 并发度, 默认值为 1
       concurrency = 1,
   }
 
   if not ok then
       ngx.log(ngx.ERR, "=======> failed to spawn health checker: ", err)
       return
   end
}
#如果有多个,在这里继续写

# 配置监控检查访问页面(放到server下面)
location /server/status {
  access_log off;
  default_type text/plain;
  content_by_lua_block {
      local hc = require "resty.upstream.healthcheck"
      ngx.say("Nginx Worker PID: ", ngx.worker.pid())
      ngx.print(hc.status_page())
  }
}

nginx reload之后访问/server/status就可以看到结果。

发版脚本

APP_START_TIMEOUT=50     # 等待应用启动的时间
APP_PORT=8080          # 应用端口
HEALTH_CHECK_URL=http://127.0.0.1:${APP_PORT}/health  # 应用健康检查URL
health_check() {
    exptime=0
    echo "checking ${HEALTH_CHECK_URL}"
    while true
    do
        status_code=`/usr/bin/curl -L -o /dev/null --connect-timeout 5 -s -w %{http_code}  ${HEALTH_CHECK_URL}`
        if [ x$status_code != x200 ];then
            sleep 1
            ((exptime++))
            echo -n -e "\rWait app to pass health check: $exptime..."
        else
            break
        fi
        if [ $exptime -gt ${APP_START_TIMEOUT} ]; then
            echo 'app start failed'
            exit 1
        fi
    done
    echo "check ${HEALTH_CHECK_URL} success"
}
UPSTREAM_NAME=api
SERVER_NAME=172.31.164.48:8081
ONLINE_OFFLINE_WAIT_TIME=6  # 实例上下线的等待时间
OFFLINE_URL=/upstreams/${UPSTREAM_NAME}/${SERVER_NAME}/down
ONLINE_URL=/upstreams/${UPSTREAM_NAME}/${SERVER_NAME}/up
online() {
    status_code=`/usr/bin/curl -L -o /dev/null --connect-timeout 5 -s -w %{http_code}  ${ONLINE_URL}`
    if [ x$status_code = x200 ];then
       sleep ${ONLINE_OFFLINE_WAIT_TIME}
    else
       echo 'app online failed'
       exit 1
    fi      
}
offline() {
    status_code=`/usr/bin/curl -L -o /dev/null --connect-timeout 5 -s -w %{http_code}  ${OFF_LINE_URL}`
    if [ x$status_code = x200 ];then
       sleep ${ONLINE_OFFLINE_WAIT_TIME}
    else
      echo 'app offline failed'
       exit 1
    fi 
}

你可能感兴趣的:(linux,nginx)