You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
建议优化 Nginx 配置项 client_body_buffer_size,提高请求 body 读取效率。建议设置 client_body_buffer_size 64k。
更多
分析 resty.http 库源码,看是否能对读写进行优化;
预计很快 Openresty 的 API 就会支持 http2.0,到时候再替换回来;
附
问题相关代码片段
access_by_lua_block {
local http = require "resty.http"
local httpc = http.new()
httpc:set_timeout(300)
httpc:set_proxy_options({http_proxy = "http://127.0.0.1:9107"})
ngx.req.read_body()
local req_method = ngx.req.get_method()
local req_body = ngx.req.get_body_data()
local req_headers = ngx.req.get_headers()
local req_url = "http://" .. ngx.var.host .. "/__to_waf__" .. ngx.var.uri
if ngx.var.is_args == "?" then
req_url = req_url .. "?" .. ngx.var.query_string
end
local res, err = httpc:request_uri(req_url, {
version = 1.1,
method = req_method,
body = req_body,
headers = req_headers,
keepalive_timeout = 60,
keepalive_pool = 16,
})
if not res then
ngx.log(ngx.ERR, "failed to request: ", err, ". url: ", req_url)
return ngx.exit(ngx.OK)
end
local status = res.status or 0
local body = res.body
if status == 200 then
if not body or body == "" then
return ngx.exit(ngx.HTTP_CLOSE)
end
elseif status == 403 or status == 400 then
ngx.req.set_method(ngx.HTTP_GET)
return ngx.exec("/__waf_page__/" .. status .. ".html")
end
}
The text was updated successfully, but these errors were encountered:
问题描述
某产品对接最新版 waf proxy(支持 http2.0)后,上传图片超时,其他请求正常。
问题分析
从 Nginx 的 error 和 access 日志发现,请求转发到 WAF 超时(超过 60 秒),导致客户端主动断开连接(499 状态)。
为了兼容 http2(构建子请求时,将http2 改写成 http1.1),我们使用开源库 resty.http 代替了原来 Openresty 原生的 API ngx.location.capture,性能下降很大,因为
ngx.location.capture
是 Nginx 子请求,本质上不是 http 请求,直接运行在 C 语言级别,效率非常高。当 POST body 数据较大时,这个库转发的速度会非常慢,从而引起超时。
经过多次对比测试发现,跟 client_body_buffer_size 设置的大小有关,当请求 body 大于
client_body_buffer_size
设置的值时,请求就会变得很慢,甚至超时;反之则正常。client_body_buffer_size
用来指定 Nginx 读取请求 body 的 buffer 大小值,默认是 8k(32位操作系统)当请求的 body 大于这个值,则会将剩余的字节写入本地文件(磁盘)。所以,根本原因是resty.http
库转发请求读写磁盘文件效率太低。解决方案
可以从两方面进行优化解决:
resty.http
转发的超时时间(httpc:set_timeout(300)
不超过 300 毫秒),因为是转发 WAF 是旁路
逻辑,可以避免转发 WAF 过慢影响客户正常业务请求。影响就是较大 body(大于client_body_buffer_size
设置大小) 不会经过 WAF 检测,其实,考虑到性能等问题,WAF 也基本不会处理较大 body (> 1M ) 。client_body_buffer_size
,提高请求 body 读取效率。建议设置client_body_buffer_size 64k
。更多
resty.http
库源码,看是否能对读写进行优化;附
问题相关代码片段
The text was updated successfully, but these errors were encountered: