ひさびさにnginxなどいじっている。
nginxがnon-blockingで動いているので、組み込みのPerlでもblockingする処理をいれることはおすすめされていないのですが、sleepだけは機能が用意されていました。使い道がよくわからないけど、とりあえずレスポンスを遅延させるのだけやってみた。
まず、handlerとなるperlモジュール
package delay;
use nginx;
sub handler {
my $r = shift;
my $args = $r->args;
$args =~ m/sleep=([^&]+)/;
my $sleep = $1 || 1;
$r->variable("sleep", $sleep);
if ( $sleep ne "no" ) {
$r->sleep($sleep * 1000, \&next);
return;
}
$r->send_http_header("text/html");
$r->print("<html><head><title>title</title></head><body>sleep:$sleep</body></html>\n");
return OK;
}
sub next {
my $r = shift;
my $sleep = $r->variable("sleep");
$r->send_http_header("text/html");
$r->print("<html><head><title>title</title></head><body>sleep:$sleep</body></html>\n");
return OK;
}
1;
このコードの中の$r->sleepが遅延実行ようにするところ
$r->sleep( msec, func )
となるようです。
これを利用するnginx.conf
worker_processes 16;
events {
worker_connections 32768;
}
http {
include /usr/local/nginx-server/conf/mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
keepalive_timeout 60;
perl_modules /path/to/lib;
perl_require delay.pm;
server {
listen 80;
server_name localhost;
access_log off;
location / {
perl delay::handler;
}
}
}
ApacheBenchでベンチマークをとったところ、
ab -c 1000 -n 100000 'http://localhost/?sleep=0.1'
Concurrency Level: 1000
Time taken for tests: 10.449 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 19100000 bytes
HTML transferred: 6900000 bytes
Requests per second: 9570.41 [#/sec] (mean)
Time per request: 104.489 [ms] (mean)
Time per request: 0.104 [ms] (mean, across all concurrent requests)
Transfer rate: 1785.11 [Kbytes/sec] received
想定通り、1コネクションあたり10req/secできるみたい。
これだけだと使い道があまりわからないだけど、nginxのevent loopが組み込みperlから利用できるようになる最初の一歩だと期待すればwktkです。
あと、調べた感じ、組み込みperlを入れるオーバーヘッドは5%ぐらいだった。7万req/secが6万6千req/secぐらい