如何在waf上用共享内存缓存压缩过的响应内容

需求

/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

计划开源中......

https://github.com/ACGNSEC/olwaf

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值