dnsdist: implement own rate-limiting function - Part 2
In previous post, I explained how I wrote a rate limiter for dnsdist using fixed window algorithm and redis. In this post, I will show how I write a rate limiter without Redis, this method give me a higher performance.
Dependencies
Install dependencies
$ apt-get install lua5.1 libpsl-dev cmake
$ luarocks install psl
$ luarocks install effil
In this way, I will use effil to create a Lua table to store counters. And it’s thread-safe.
local effil = require("effil")
local request_counters = effil.table()
Continue, create a simple counter function
function increment(counters, domain, current_time, window_size)
if not counters[domain] then
counters[domain] = {
expire_at = current_time + window_size,
count = 0
}
end
local counter = counters[domain]
if counter["expire_at"] <= current_time then
counter["count"] = 0
counter["expire_at"] = current_time + window_size
end
counter["count"] = counter["count"] + 1
return counter["count"]
end
In rate limiting function, increase counter then get current rate
local current_time = os.time()
local rate = increment(request_counters, domain, current_time, window_size)
At last, I created a cleanup function to remove the expire counter. This function would be ran in another thread every 5 seconds
function cleanup(counters)
while true do
for domain, counter in effil.pairs(counters) do
if counter["expire_at"] < os.time() and counter["count"] > 0 then
counters[domain] = nil
end
end
effil.sleep(5, "s")
end
end
effil.thread(cleanup)(request_counters)
Benchmark
Dnsdist without Rate limiter
root@test1:~# ./dnsstresss -r 127.0.0.1:53 google.com
dnsstresss - dns stress tool
Testing resolver: 127.0.0.1:53.
Target domains: [google.com.].
Started 50 threads.
Requests sent: 10749r/s Replies received: 10749r/s (mean=5ms / max=27ms)
Requests sent: 11245r/s Replies received: 11245r/s (mean=4ms / max=15ms)
Requests sent: 11459r/s Replies received: 11459r/s (mean=4ms / max=23ms)
Requests sent: 11085r/s Replies received: 11085r/s (mean=5ms / max=20ms)
Requests sent: 10936r/s Replies received: 10936r/s (mean=5ms / max=18ms)
Dnsdist with Rate limiter (with redis)
root@test1:~# ./dnsstresss -r 127.0.0.1:53 google.com
dnsstresss - dns stress tool
Testing resolver: 127.0.0.1:53.
Target domains: [google.com.].
Started 50 threads.
Requests sent: 5774r/s Replies received: 5774r/s (mean=8ms / max=25ms)
Requests sent: 5055r/s Replies received: 5055r/s (mean=10ms / max=24ms)
Requests sent: 5125r/s Replies received: 5125r/s (mean=10ms / max=25ms)
Requests sent: 5232r/s Replies received: 5232r/s (mean=10ms / max=30ms)
Requests sent: 5050r/s Replies received: 5050r/s (mean=10ms / max=23ms)
Dnsdist with Rate limiter (without redis)
root@test1:~# ./dnsstresss -r 127.0.0.1:53 google.com
dnsstresss - dns stress tool
Testing resolver: 127.0.0.1:53.
Target domains: [google.com.].
Started 50 threads.
Requests sent: 11649r/s Replies received: 11649r/s (mean=4ms / max=17ms)
Requests sent: 10926r/s Replies received: 10926r/s (mean=5ms / max=23ms)
Requests sent: 11200r/s Replies received: 11200r/s (mean=4ms / max=17ms)
Requests sent: 11417r/s Replies received: 11417r/s (mean=4ms / max=20ms)
Requests sent: 10413r/s Replies received: 10413r/s (mean=5ms / max=19ms)
Read other posts