Skip to content

Instantly share code, notes, and snippets.

@lcrilly
Created May 17, 2024 17:01
Show Gist options
  • Save lcrilly/6b5cd08a9b3bc0ba8d24e3764dcfde08 to your computer and use it in GitHub Desktop.
Save lcrilly/6b5cd08a9b3bc0ba8d24e3764dcfde08 to your computer and use it in GitHub Desktop.
Implementing a sin bin with NGINX Plus
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