Openresty在运维工作中的运用

Openresty在运维工作中的运用

杨滔@猪八戒网运维取经团

一 介绍

1.1 openresty

OpenResty is a dynamic web platform based on NGINX and LuaJIT.

hadas_openresty_in_maintain_1_logo

1.2 作者

章亦春

男,曾任CloudFlare Inc.系统工程师。

章亦春在北京工作四年,最早在雅虎中国写火狐浏览器扩展和网页信息抽取器,接着在淘宝做数据产品平台。

二 基金会

hadas_openresty_in_maintain_1_foundation

用了整整一年的时间, OPENRESTY SOFTWARE FOUNDATION LIMITED 终于通过香港税务局的审批,按照《税务条例》88条成为豁免缴税的慈善机构! 这是中国第一家,也是唯一一家获得合法资质的软件基金会。 捐赠者会收到正式的捐助收据,超过 100 港币的捐赠,可以在香港抵税。

2016 con

hadas_openresty_in_maintain_1_con

四 预备知识普及

  1. Lua 多使用局部变量(local)
  2. Lua 没有数组或字典,只有table,{“hello” ,33},{ [“flag” ] = “aa”, 11}, {[“flag” ] = {[“flag” ] = true}}
  3. Table 下标从1开始
  4. Table 类型是引用,数字类型不是
  5. 多使用openresty的函数,如ngx.md5
  6. Nginx有不用执行阶段,完成不同的工作
  7. 使用时在nginx.conf添加配置如
  8. access_by_lua_file /etc/lua/a.lua;
  9. init_work_by_lua_file /etc/lua/b.lu
  10. Lua工作在Nginx 自身阶段之后
  11. 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 用途

  1. 请求准入控制,或者说安全控制。
  2. 定制请求(header增删改)等。

5.1.5 其他例子

5.1.5.1运维平台的小应用必须经过平台的授权才可以访问。

由运维平台跳转进入小应用,进入url样式:a.zbj.com/?code=abcde, 解码code验证后方可访问,使用cookie维持状态。

用途:处理URL,加密解密URL、重写重定向等。

hadas_openresty_in_maintain_1_flow_a

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 用途

  1. 定制请求。
  2. 屏蔽恶意请求,优化资源使用。
  3. 当然,还可以解决OKR(非正常请求的5xx报错)。

5.3 return 200

5.3.1 需求:某些情况下(比如新上线的url严重影响后端),我们不得不使某些url 直接返回而不是访问后端。

5.3.2 常规做法:修改nginx文件,提交git,审核上线,reload nginx生效。

5.3.3 新做法

hadas_openresty_in_maintain_1_flow_b

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其他例子

  1. 实时更新黑名单IP,屏蔽之。
  2. 根据词库单独记录敏感请求日志,以供分析。
  3. 不用reload的动态路由(upstream)。

OpenResty中文编程:编辑整理