nginx+lua(openresty)实现灰度发布及负载均衡-hash key绑定

nginx+lua(openresty)+redis实现灰度发布及ngxin负载均衡,hash key绑定指定ID,所有客户端访问相同id的时候都连接同一台服务器处理。这种情况大多用在某业务功能的服务器集群,某个产品详情页只缓存在其中一台服务器中,而不是所有集群中的服务器都去缓存一次。

过程中使用的服务软件:nginx,redis,lua,php-swoole


运行方式:nginx作为网关或连接服务端,在content_by_lua_file(nginx在内容处理阶段执行lua文件脚本),swoole启动三个http服务,分别为9501,9502,9503端口,负载均衡分别到三台http服务。


实现过程:

一、nginx.conf配制

        http块中配制如下语句:

#lua指定在什么位置查找包 绝对路径
lua_package_path "/data/openresty/lualib/project/common/?.lua;;";

        增加两个负载均衡,其中一个启用hash key  用于对所有请求的同一个ID都转发到同一个服务器

upstream client1 {
   hash $key; #进行hash key
   server 127.0.0.1:9501; #模拟生成服务器
   server 127.0.0.1:9503;
}
upstream client2 {
   server 127.0.0.1:9502; #模拟生成服务器
}

        在server块中增加location块 及一个if语句块

#url请求过来时候,通过url中的一个特定数值(id),进行提取,然后进行hash key
if ( $request_uri ~* ^\/.*id=(\d+).* ) {
    set $key $1;
}

location /test {
   content_by_lua_file "/data/openresty/lualib/project/grays/Grayscale.lua";
}

        通过代理访问两个负载均衡块

location @client_1 {
   proxy_pass http://client1;
}
location @client_2 {
   proxy_pass http://client2;
}

二、lua脚本Grayscale.lua

ngx.header.content_type="text/html; charset=utf-8";
ngx.header.Server="open";

--IP
local local_ip = ngx.var.remote_addr
if local_ip == nil then
    ngx.log(ngx.ERR, "LOCAL_IP---", local_ip)
end
--ngx.say(local_ip)

--lualocal tool = require "tool"
local allowIp,err = tool:allow(local_ip)
if allowIp == nil then
    --ngx.say("没有IP")
    ngx.exec("@client_1") --发送一个内部请求
    return
else
    ngx.exec("@client_2") --发送一个内部请求
    --ngx.say(allowIp)
    return
end

三、lua脚本 tool.lua

此脚本放到common中lua通过配制lua_package_path路径自动扫描并加载

--tool模块

local tool = {}
tool.default_ip = "127.0.0.1"
tool.default_port=6379

local redis = require "resty.redis"

--连接redis
function tool.connectRedis(self)
    local red, err = redis:new()
    local ok, err = red:connect(self.default_ip, self.default_port)

    if not ok then
        ngx.log(ngx.ERR, "failed to connect:", err)
        return
    end

    --redis认证
    local res, err = red:auth("111111")
    if not res then
        ngx.log(ngx.ERR, "failed to authenticate:", err)
        return
    end

    return red
end

--判断客户端IP是否存在
function tool.allow(self, key)
    local redi = self:connectRedis()

    ---redi:set(key,"2225522")
    local allow_value,err = redi:get(key)
    redi:close()

    if not allow_value then
        ngx.log(ngx.ERR, "failed to get ip: ", err)
        return
    end
    --ngx.say(allow_value)

    if allow_value == ngx.null then
        ngx.log(ngx.ERR, "local_ip not found.")
        return
    end

    return(allow_value)

end

--最终返回table
return tool


猜您喜欢
    0条评论