30-多级缓存架构-分发层缓存实现-部署分发层nginx以及基于lua完成基于商品id的定向流量分发策略


基于OpenResty在另外两台机器上都部署一下nginx+lua的开发环境

我已经在01、02和03上都部署好了

是打算用01和02作为应用层nginx服务器,用03作为分发层nginx。

在03,也就是分发层nginx中,编写lua脚本,完成基于商品id的流量分发策略

当然了,我们这里主要会简化策略,简化业务逻辑,实际上在你的公司中,你可以随意根据自己的业务逻辑和场景,去制定自己的流量分发策略

策略:

1、获取请求参数,比如productId
2、对productId进行hash
3、hash值对应用服务器数量取模,获取到一个应用服务器
4、利用http发送请求到应用层nginx
5、获取响应后返回

这个就是基于商品id的定向流量分发的策略,lua脚本来编写和实现

我们作为一个流量分发的nginx,会发送http请求到后端的应用nginx上面去,所以要先引入lua http lib包

cd /opt/openrestydir/hello/lualib/resty/  
wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http_headers.lua  
wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http.lua 

代码:

# 通过函数获取请求参数
local uri_args = ngx.req.get_uri_args()
# 获取参数productId
local productId = uri_args["productId"]

# 应用层nginx的host
local host = {"192.168.1.51", "192.168.1.52"}
# 获取productId的hash值
local hash = ngx.crc32_long(productId)
# 使用hash值对nginx应用层数量进行取模
hash = (hash % 2) + 1  
backend = "http://"..host[hash]

# 获取方法
local method = uri_args["method"]
# 拼装请求req
local requestBody = "/"..method.."?productId="..productId

# 获取http对象
local http = require("resty.http")  
local httpc = http.new()  

# 发送请求
local resp, err = httpc:request_uri(backend, {  
    method = "GET",  
    path = requestBody,
    keepalive=false
})

if not resp then  
    ngx.say("request error :", err)  
    return  
end

ngx.say(resp.body)

/usr/servers/nginx/sbin/nginx -s reload

 

OpenResty HTTP库 request_uri方法set_keepalive报错源码中的BUG分析

用lua去写分发的逻辑,在分发层nginx里去写的,发现OpenResty最新的 http.new() new出来的对象request_uri方法老是报错,原来一直都是这样就可以的
local resp, err = httpc:request_uri(hostUrl, {
method = “GET”,
path = requestBody
})
结果居然报错了,提示
lua entry thread aborted: runtime error: /usr/hello/lualib/resty/http.lua:909: bad argument #2 to ‘set_keepalive’ (number expected, got nil)
以前做类似的分发代码的时候,request_uri方法是从来不会报错的,反复检查自己代码很多遍,应该没问题才是,然后直接去看http.lua源码了,来到909行

分析说明:
若params 也就是之前我们请求时带的关联数组
{
method = “GET”,
path = requestBody
} 这一坨中keepalive这个属性不为假 那就调用self:set_keepalive方法,然后这方法调用失败了,因为我们没有在params传参数进去
直接报number expected, got nil,参数为空
不知道大家有没有发现什么问题,其实是OpenResty源码这一块有问题,他不应该去判断是否keepalive为假,因为keepalive这个参数不填的时候,lua的语言性质决定了,这个地方会返回假 因为nil == false会返回假 所以就执行了有keepalive的逻辑 不信的同学可以用lua交互式模式打印一下 print(nil == false) 会返回假的 所以本来空值的时候不该走下面的流程的,但是由于编码疏忽,没有实现相应的效果

 

临时解决方案:
在关联数组中多传一个参数keepalive=false 即
{
method = “GET”,
path = requestBody,
keepalive=false
}
显式的给keepalive传递一个false 避免发生这样的问题

 

å¨è¿éæå¥å¾çæè¿°

 

基于商品id的定向流量分发策略的lua脚本就开发完了,而且也测试过了

我们就可以看到,如果你请求的是固定的某一个商品,那么就一定会将流量打到固定的一个应用nginx上面去.
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值