需求是现在有些post请求的内容导致我们某个应用压力巨大,而正常是同样post的内容在24小时内只会请求一次。

初步思路就是将post内容里的变量部分写入到redis中,然后设置过期时间为1天。这样每次post的时候先查一下redis是否存在这个key。有就直接转到google上,没有就继续proxy_pass。 这里面会有几个坑。

不过lua我是第一次写,所以很多问题都没有提前预计到,测试的时候发生了很多问题。

首先自然是加入nginx-lua-redis模块支持。这里碰到个问题,ngx.say以后要是不加return就会报错。然后模块在应用的时候也要注意一下。


lua_package_path "/etc/nginx/lua/lua-resty-redis/lib/?.lua;;";

自己写一个lua模块。


local redis = require "resty.redis"
local cache = redis.new()
local ok, err = cache.connect(cache, '127.0.0.1', '6379')
ngx.req.read_body()
local method   = ngx.var.request_method

cache:set_timeout(60000)

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

if method == 'POST' then
local data = ngx.req.get_body_data()
if data then
local i = ngx.re.match(data, "[0-9]{11}")
local phone = i[0]
local exist = cache:exists(phone)
if exist == 0 then
cache:set(phone, "phone")
cache:expire(phone, 86400)
else
ngx.redirect("http://www.google.com", 302)
ngx.say(phone, ' is in baned')
return ngx.exit(403)
--            ngx.say(phone, ' is in baned')
--            return ngx.exit(403)
end
end
end

local ok, err = cache:close()

if not ok then
--        ngx.say("failed to close:", err)
return
end

在location中进行应用。这里要用access_lua_by_file, 而不是 content_lua_by_file。但是用access_lua_by_file的时候必须要retrun好,如果return 200的话会继续proxy_pass, 其他的就直接返回了。


location = /VerifyCode {
access_by_lua_file /etc/nginx/conf.d/include/ban-phone-number.lua;

proxy_pass http://test;
}

Share Your Thought