使用 HAProxy 对大型 Post 请求进行速率限制
Rate Limiting using HAProxy with Large Post Requests
我在 API 前使用 HAProxy v2.0.13,并尝试实施基于 URL 的速率限制,以尝试在 30 分钟内将连接限制为 5 个 window “/get_link”路径的每个源 IP:
frontend fe_dev
mode http
bind *:8081,[::]:8081
stick-table type ip size 100k expire 30m store http_req_rate(30m)
http-request track-sc0 src if METH_POST { path -i -m beg /get_link }
http-request deny deny_status 429 if { sc_http_req_rate(0) gt 5 }
default_backend be_dev
此 API 端点是使用 XMLHttpRequest()
请求从 JavaScript 函数调用的,我正在使用 Google Chrome v83.
var xHR = new XMLHttpRequest();
xHR.open("POST", "get_link", true);
xHR.onload = function() {
console.log('status code is ' + this.status);
};
xHR.onerror = function() {
console.log("onerror()");
};
var obj = {};
xHR.setRequestHeader("Content-Type", "application/json");
xHR.send(JSON.stringify(obj));
当我的 POST 请求的大小很小(即几百个字节)时,一切正常 - 在 5 个请求后,我开始收到 HTTP 429 返回。然后我尝试了一个大的 POST 请求(内容长度约为 35500 字节),这是 Chrome 开始触发 onerror
函数的时候。
我已经完成了 tcpdump
,看起来 HAProxy 在发回 429 之前没有等待整个请求(输出为简洁起见进行了修剪):
POST /get_link HTTP/1.1
Host: server:8081
Connection: keep-alive
Content-Length: 35687
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://server:8081
Referer: http://server:8081/index.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
{"req1":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 429 Too Many Requests
content-length: 117
cache-control: no-cache
content-type: text/html
connection: close
<html><body><h1>429 Too Many Requests</h1>
You have sent too many requests in a given amount of time.
</body></html>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
通过查看 tcpdump
我还可以看到 HAProxy 在发回 429 后立即发送 TCP RST,即使 Chrome 仍在发送 POST 数据。如何让 HAProxy 正常运行并等到它收到整个请求后再拒绝它?
没有人想到的答案是启用“option http-buffer-request”。
我在 API 前使用 HAProxy v2.0.13,并尝试实施基于 URL 的速率限制,以尝试在 30 分钟内将连接限制为 5 个 window “/get_link”路径的每个源 IP:
frontend fe_dev
mode http
bind *:8081,[::]:8081
stick-table type ip size 100k expire 30m store http_req_rate(30m)
http-request track-sc0 src if METH_POST { path -i -m beg /get_link }
http-request deny deny_status 429 if { sc_http_req_rate(0) gt 5 }
default_backend be_dev
此 API 端点是使用 XMLHttpRequest()
请求从 JavaScript 函数调用的,我正在使用 Google Chrome v83.
var xHR = new XMLHttpRequest();
xHR.open("POST", "get_link", true);
xHR.onload = function() {
console.log('status code is ' + this.status);
};
xHR.onerror = function() {
console.log("onerror()");
};
var obj = {};
xHR.setRequestHeader("Content-Type", "application/json");
xHR.send(JSON.stringify(obj));
当我的 POST 请求的大小很小(即几百个字节)时,一切正常 - 在 5 个请求后,我开始收到 HTTP 429 返回。然后我尝试了一个大的 POST 请求(内容长度约为 35500 字节),这是 Chrome 开始触发 onerror
函数的时候。
我已经完成了 tcpdump
,看起来 HAProxy 在发回 429 之前没有等待整个请求(输出为简洁起见进行了修剪):
POST /get_link HTTP/1.1
Host: server:8081
Connection: keep-alive
Content-Length: 35687
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://server:8081
Referer: http://server:8081/index.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
{"req1":"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 429 Too Many Requests
content-length: 117
cache-control: no-cache
content-type: text/html
connection: close
<html><body><h1>429 Too Many Requests</h1>
You have sent too many requests in a given amount of time.
</body></html>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
通过查看 tcpdump
我还可以看到 HAProxy 在发回 429 后立即发送 TCP RST,即使 Chrome 仍在发送 POST 数据。如何让 HAProxy 正常运行并等到它收到整个请求后再拒绝它?
没有人想到的答案是启用“option http-buffer-request”。