需求
/auto-api/v1/regions接口响应内容比较大近800k,为了达到快速响应,给客户端带来更好的体验。减少请求延迟,减小网络传输带宽势在必行,不然会给业务端和带宽带来巨大的压力。
减小请求延迟办法:将响应内容在waf上进行缓存。
减小网络传输带宽办法:将响应内容压缩。
备注:需要客户端支持解压缩。
请求响应链路
蓝色请求响应线为原始路径。
黄色请求响应线为预期效果,由此可见原始链路越长,该方案加速效果越明显。
解决办法
将指定接口的响应body压缩后,在waf server上进行缓存至share dict,缓存key的键值为域名+url。
当客户端请求该接口时,直接从waf server缓存中获取响应内容返回给客户端。
因为该接口响应内容是压缩过的body,当该响应返回给客户端时,要通知客户端进行解压,所以呢...,响应头中增加了Content-Encoding:gzip。原因如下:
客户端发送请求时,通过Accept-Encoding告诉服务端自己支持的内容编码列表。
服务端挑选一种对响应body进行编码,然后通过Content-Encoding响应头通知客户端所选定的格式。
客户端拿到响应body后,根据Content-Encoding格式进行解压。
编码
header_filter_by_lua_file
header_filter_by_lua_file /opt/olwaf/header.lua;
if ngx.var.uri == "/auto-api/v1/regions" then
ngx.header["Content-Length"] = nil
ngx.header["Content-Encoding"] = "gzip"
end
body_filter_by_lua_file
body_filter_by_lua_file /opt/olwaf/body_filter.lua;
local _M = {}
local request = require "request"
local zlib = require "resty.ffi-zlib"
local next_tb = ngx.ctx.next_tb or {}
local uncompressed = ''
local body_dict = ngx.shared.body_dict
local function zlib_compress(input_data)
local _input_data = input_data
local count = 0
local input = function(bufsize)
local start = count > 0 and bufsize*count or 1
local data = _input_data:sub(start, (bufsize*(count+1)-1))
if data == "" then
data = nil
end
count = count + 1
return data
end
local output_table = {}
local output = function(data)
table.insert(output_table, data)
end
local chunk = 16384
local ok, err = zlib.deflateGzip(input, output, chunk)
if not ok then
ngx.log(ngx.ERR,err)
end
local compressed = table.concat(output_table,'')
return compressed
end
local function rsp_body_compress()
local Content_Disposition = ngx.resp.get_headers()['Content-Disposition']
local Content_Type = ngx.resp.get_headers()['Content-Type']
local check_content_type
if Content_Type then
check_content_type = ngx.re.find(Content_Type, [=[text|json|xml|javascript]=],"oij")
end
if (not Content_Disposition) and check_content_type and (#ngx.arg[1] ~= 0) then
end
local body = body_dict:get("/mall-unit-api/v1-0/regions2")
if not _nginx_host then
local compressed = zlib_compress(ngx.arg[1])
--压缩后暂时永久缓存
body_dict:set("/auto-api/v1/region", compressed, 0)
end
--ngx.arg[1]为response body
local compressed = body_dict:get("/auto-api/v1/regions")
ngx.arg[1] = compressed
return compressed
end
if ngx.var.uri == "/auto-api/v1/regions" then
local body = rsp_body_compress()
--ngx.log(ngx.ERR , body)
end
return _M
关于olwaf
计划开源中......