Created
May 17, 2024 17:01
-
-
Save lcrilly/6b5cd08a9b3bc0ba8d24e3764dcfde08 to your computer and use it in GitHub Desktop.
Implementing a sin bin with NGINX Plus
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
limit_req_zone $remote_addr zone=per_ip:1M rate=5r/s sync; # Cluster-aware rate limiting | |
limit_req_status 429; | |
keyval_zone zone=sinbin:1M timeout=60 sync; | |
keyval $remote_addr $sinbin_rate zone=sinbin; | |
# Frontend | |
# | |
server { | |
listen 80; | |
location / { | |
set $limit_rate $sinbin_rate; | |
limit_req zone=per_ip burst=1; | |
error_page 429 = @send_to_sinbin; | |
proxy_set_header sinbin $limit_rate; | |
proxy_pass http://local_backend; | |
} | |
location @send_to_sinbin { | |
# Make this look like a successful request, proxy to the backend as normal | |
# but use mirror to make an async call to add to sinbin. | |
# | |
mirror /_api_call; | |
proxy_set_header sinbin send_to_sinbin; | |
proxy_pass http://local_backend; | |
} | |
location /_api_call { | |
internal; | |
if ($sinbin_rate) { | |
return 204; # Don't attempt second POST (it will 409) | |
} | |
rewrite ^ /api/3/http/keyvals/sinbin break; | |
proxy_method POST; | |
proxy_set_body '{"$remote_addr":50}'; # Value is bandwidth limit (limit_rate) | |
proxy_pass http://local_api; # Proxy to upstream so that we can control connections to API | |
} | |
location = /favicon.ico { return 204; } | |
location /api/ { api write=on; } | |
} | |
server { | |
listen 8081; | |
location /api/ { | |
allow 127.0.0.1; | |
deny all; | |
api write=on; | |
} | |
} | |
server { | |
listen 10001; | |
location / { | |
add_header Content-Type text/html; | |
return 200 '<html> | |
<head> | |
<meta http-equiv="refresh" content="2" /> | |
<meta http-equiv="cache-control" content="no-cache" /> | |
<meta http-equiv="expires" content="0" /> | |
<title>Backend server</title> | |
</head> | |
<body bgcolor=#$request_id> | |
<h2>Backend server</h2> | |
<h3>Sin bin status $http_sinbin</h3> | |
<hr size=1><tt>$time_local</tt> | |
</body> | |
</html>\n'; | |
#return 200 'This is the local backend\n\nSin Bin status: $http_sinbin\n'; | |
} | |
} | |
upstream local_backend { | |
zone local_backend 64k; | |
server 127.0.0.1:10001; | |
} | |
upstream local_api { | |
zone send_to_sinbin 64k; | |
server 127.0.0.1:8081 max_conns=1; | |
queue 10 timeout=30; | |
} | |
# vim: syntax=nginx |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment