Passenger vs puma

2024-07-27 ruby rails linux

RaspberryPiでPhusion Passengerが使えないという場面に出くわしてから、Railsを動かす構成について幾つか検討をしていました。なんとなく流れでapacheからnginxへの移行も考えたのですが、よく考えたら別にApache(http server)が悪いわけではないので、そちらはボツに。Passengerの代わりにPumaをそのまま使えばいいんじゃないか、と原点に立ち戻ってみましたが、certbot(letsencrypt)の証明書をうまく読み込めないので単体で動かすのもボツ(自分でコピーしてくればいけるんですが、更新がめんどくさくなりそう)。

ということで、Apache + Pumaを組み合わせて以下のようにプロキシモジュールで対応しています。

ProxyPass / http://localhost:3001/
ProxyPassReverse / http://localhost:3001/

これまで多くの環境で導入してきたApache + Passengerは以下のような感じ。

DocumentRoot /var/www/myapp/public
PassengerAppEnv production
PassengerRuby /home/lmuser/.rbenv/versions/3.1.5/bin/ruby

同じサーバで上記2つの設定を入れ替えてレスポンスを比較してみました。使用したのは ab コマンドで、以下が実際に与えたパラメタと共通の出力部分(抜粋)です。

ab -n 10000 -c 100 https://foobar.lmlab.net/testpath
Server Software:        Apache/2.4.58
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-ECDSA-CHACHA20-POLY1305,256,256
Server Temp Key:        ECDH X25519 253 bits
:
Concurrency Level:      100
Document Length:        11820 bytes
:

結果はそれぞれ以下の通り。

Apache + Puma(6.4.2):

Time taken for tests:   239.695 seconds
Complete requests:      10000
Failed requests:        0
Requests per second:    41.72 [#/sec] (mean)
Time per request:       2396.951 [ms] (mean)
Time per request:       23.970 [ms] (mean, across all concurrent requests)
Transfer rate:          513.92 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      119  225 281.3    157    2385
Processing:    65 2154 12638.1   1474  231541
Waiting:       63 2151 12638.2   1472  231540
Total:        198 2379 12647.2   1642  231810

Apache + Passenger(6.0.17):

Time taken for tests:   156.430 seconds
Complete requests:      10000
Failed requests:        2
   (Connect: 1, Receive: 0, Length: 1, Exceptions: 0)
Requests per second:    63.93 [#/sec] (mean)
Time per request:       1564.297 [ms] (mean)
Time per request:       15.643 [ms] (mean, across all concurrent requests)
Transfer rate:          797.64 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0  180  41.2    174     815
Processing:    83 1375 166.5   1372   14995
Waiting:       74 1370  93.9   1369    1993
Total:        265 1554 161.4   1546   14995

Passengerの方が幾分応答が速いですが、1万回のリクエストの中で2回エラーが発生しています。対するPumaはエラーこそ0ですが、ものすごく時間がかかってるレスポンスも存在します。単にタイムアウトの規定値の違いでしょうか?(今回そうしたパラメタは全く触っておらず、規定値のまま動作しています)

あと、Pumaの方は以下のオプションを有効にしています。

Environment="RAILS_SERVE_STATIC_FILES=true"

以下の要領でプロキシの対象から除外してDocumentRootを読ませれば、Pumaを介さずに配信可能ですが、結果にほとんど差は見られませんでした。

ProxyPass /assets !
DocumentRoot /var/www/myapp/public

Passengerは導入がややこしかったりするので、そういう場面ではPumaを使ってもいいのかな、という感じで捉えておこうと思います。