C10K対応Prefork型高速PSGI/Plackサーバの Monoceros をHTTP/1.1に対応させました。

https://metacpan.org/release/Monoceros
https://github.com/kazeburo/Monoceros

MonocerosではHTTPのKeepAliveに対応して、大量の接続を捌く事ができますが、リリース時点ではHTTP/1.0 KeepAliveにしか対応していませんでした。しかし、nginxのupsream などでは、keepaliveを有効にしてHTTPセッションを使い回したい場合にHTTP/1.1が求められます。

monoceros-keepalive.png

以前このあたりの事をしらべてblog書いています

nginx-1.1.x で httpなupstreamにもkeepaliveができるようになったので検証してみた
http://blog.nomadscafe.jp/2012/02/nginx-11x-httpupstreamkeepalive.html

これではMonocerosが活かせないということで既に1.1に対応しているStarmanを参考にしつつ、HTTP/1.1対応しました。対応したのは次の機能

  • KeepAlive
  • Transfer-Encoding: chunked (Request & Response)
  • HTTP Pipelining
  • Expect

これらに対応しつつ、今までのHTTP/1.0のKeepAliveも使えるようになっています。

ほとんど使われない機能ですが、HTTP Pipeliningにも対応していて

my $body = 'OK 'x10;
sub {
    [200, ['Content-Type'=>'text/plain'],[$body]]
}

こんなpsgiを書いてMonocerosを起動してncを使って2つのリクエストを続けて投げてみると、

$ cat reqs.txt 
GET /1 HTTP/1.1
Host: foo

GET /2 HTTP/1.1
Host: foo
Connection: close

$ cat reqs.txt | nc 10.xx.xx.xx 5000
HTTP/1.1 200 OK
Date: Fri, 17 May 2013 06:08:35 GMT
Server: Plack::Handler::Monoceros
Content-Type: text/plain
Transfer-Encoding: chunked

1e
OK OK OK OK OK OK OK OK OK OK 
0

HTTP/1.1 200 OK
Date: Fri, 17 May 2013 06:08:35 GMT
Server: Plack::Handler::Monoceros
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: close

1e
OK OK OK OK OK OK OK OK OK OK 
0

と、レスポンスも2つ得られました。Transfer-Encodingがchunkedにもなってますね。

Monocerosをnginx のバックエンドに設置してのベンチマーク

HTTP/1.1対応できたので、早速nginxのバックエンドにしてベンチマークしてみました。

monoceros-keepalive-bench.png

Upstream KeepAliveを有効にすると、大体倍の性能になるようですね。ベンチマークに使ったのはab、参考としてabもkeepalive on/off切り替えてデータを取得しました。なお、直接 Monocerosにアクセスすると、2万強のreq/secがでます。この差がReverse Proxyする分のオーバーヘッドですね

ベンチマークに使った環境は前回と同じ、Xeon L5630 2.13GHz 4コア/8スレッド を2つ積んだサーバです。nginxとMonocerosを同じサーバに導入し、abは別のサーバから実行しました。

ベンチマークに使ったアプリケーション

my $body = 'OK 'x10;
sub {
    [200, ['Content-Type'=>'text/plain','Content-Length'=>length($body)],[$body]]
}

残念ながら ab が Transfer-Encoding: chunked による KeepAliveに対応していないので、Content-Lengthを付けています。

Monocerosの起動は、

$ carton exec -- plackup -E production --port 5000 --max-workers=10 -s Monoceros --max-reqs-per-child=50000 -a app.psgi

nginx.confは主なところを抜き出すと以下。

worker_processes 1;
events {
    use epoll;
    worker_connections  10000;
}
http {
    keepalive_timeout      5 3;
    keepalive_requests     50000;
    upstream backend {
        server 127.0.0.1:5000;
        keepalive 100;
    }
    server {
        listen       8080;
        server_name  localhost;
        location / {
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_pass http://backend;
        }
    }
}

ab は -c 100 で実行しました。

$ ab -k -c 100 -n 50000 'http://10.xx.xx.xx:8080/

リクエストの数や接続数次第ではnginxのworker_processes/keepaliveなどの設定を変更する必要がありそうです。

このブログ記事について

このページは、Masahiro Naganoが2013年5月17日 17:19に書いたブログ記事です。

ひとつ前のブログ記事は「Monoceros というPrefork型だけどC10Kの接続を捌くことができるPSGI/Plackサーバ書きました」です。

次のブログ記事は「HTTP/1.1 の Transfer-Encoding: chunked をビジュアライズするツール書いてみた」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 4.27-ja