Openresty在运维工作中的运用
杨滔@猪八戒网运维取经团
一 介绍
1.1 openresty
OpenResty is a dynamic web platform based on NGINX and LuaJIT.
1.2 作者
章亦春
男,曾任CloudFlare Inc.系统工程师。
章亦春在北京工作四年,最早在雅虎中国写火狐浏览器扩展和网页信息抽取器,接着在淘宝做数据产品平台。
二 基金会
用了整整一年的时间, OPENRESTY SOFTWARE FOUNDATION LIMITED 终于通过香港税务局的审批,按照《税务条例》88条成为豁免缴税的慈善机构! 这是中国第一家,也是唯一一家获得合法资质的软件基金会。 捐赠者会收到正式的捐助收据,超过 100 港币的捐赠,可以在香港抵税。
三 2016 con
四 预备知识普及
- Lua 多使用局部变量(local)
- Lua 没有数组或字典,只有table,{“hello” ,33},{ [“flag” ] = “aa”, 11}, {[“flag” ] = {[“flag” ] = true}}
- Table 下标从1开始
- Table 类型是引用,数字类型不是
- 多使用openresty的函数,如ngx.md5
- Nginx有不用执行阶段,完成不同的工作
- 使用时在nginx.conf添加配置如
- access_by_lua_file /etc/lua/a.lua;
- init_work_by_lua_file /etc/lua/b.lu
- Lua工作在Nginx 自身阶段之后
- Openresty 有众多非阻塞的库,mysql、redis等
五 实例
5.1 header 验证
5.1.1需求:在nginx代理与nginx之间需要访问权限验证。
Set 端:
local set_header = ngx.req.set_header
locxiel md5 = ngx.md5
local time = ngx.time
local HashKey = "d0MMomoomd"
local HeaderTime = time()
local HeaderSec = md5(HeaderTime..HashKey)
set_header("x-yan1",HeaderTime)
set_header("x-yan2",HeaderSec)
Get 端:
local get_headers = ngx.req.get_headers
local md5 = ngx.md5
local time = ngx.time
local exit = ngx.exit
local tonumber = tonumber
local HashKey = "d0MMomoomd"
local TimeNow = time()
local HeaderTime = get_headers()["x-yan1"]
local HeaderSec = get_headers()["x-yan2"]
if not HeaderTime or not HeaderSec then
exit(403)
return
end
local MyHeaderSec = md5(HeaderTime..HashKey)
if MyHeaderSec ~= HeaderSec then
exit(403)
return
end
5.1.2 问题:header可以复用,需要优化。
5.1.3 用途
- 请求准入控制,或者说安全控制。
- 定制请求(header增删改)等。
5.1.5 其他例子
5.1.5.1运维平台的小应用必须经过平台的授权才可以访问。
由运维平台跳转进入小应用,进入url样式:a.zbj.com/?code=abcde, 解码code验证后方可访问,使用cookie维持状态。
用途:处理URL,加密解密URL、重写重定向等。
5.2 屏蔽恶意请求
5.2.1 需求:某个站点发现大量500报错,经查在报错的请求中包含大量cookie,在后端传给php时报错,认定为非法请求,需要屏蔽。报错的URL是功能性链接,有正常用户在访问,我们只能屏蔽包含了大量cookie的非法请求。
local len = string.len
local exit = ngx.exit
local uri = ngx.var.request_uri
local method = ngx.req.get_method()
local cookie = ngx.var.http_cookie
if uri == "/register/doreg" and method=="POST" then
if len(cookie) > 20580 then
ngx.log(ngx.ERR,"LARGE COOKIE ip is:"..client_ip)
exit(404)
return
end
end
5.2.2 用途
- 定制请求。
- 屏蔽恶意请求,优化资源使用。
- 当然,还可以解决OKR(非正常请求的5xx报错)。
5.3 return 200
5.3.1 需求:某些情况下(比如新上线的url严重影响后端),我们不得不使某些url 直接返回而不是访问后端。
5.3.2 常规做法:修改nginx文件,提交git,审核上线,reload nginx生效。
5.3.3 新做法
local Cache = ngx.shared.return ok
local UriCacheKey = "returnok_"..domain
local UriCache = Cache:get(UriCacheKey)
if not UriCache then
UriCache = cjson.decode(redis:get(UriCacheKey))
Cache:set(UriCacheKey,UriCache,cachetime)
local ok, err = redis:set_keepalive(10000, 100)
end
for k,v in pairs(UriCache) do
if v == "match" then
if find(uri,k,"jo") ~= nil then
exit(200)
return
end
elseif v == "=" then
if k == uri then
exit(200)
return
end
end
end
以上实例缺省部分代码。
5.3.5 用途
快速应急处理,保障整体稳定,以免影响重要项目。
5其他例子
- 实时更新黑名单IP,屏蔽之。
- 根据词库单独记录敏感请求日志,以供分析。
- 不用reload的动态路由(upstream)。
OpenResty中文编程:编辑整理