2017/05/16 v3.8.2 READMEの翻訳。
Pumaは、シンプルで、速くて、マルチスレッド、そして高い並列性を持ったRuby/RackアプリケーションのHTTP1.1サーバです。 Pumaは、開発とプロダクション環境どちらにも使えます。 ベストなスループットを得るために、スレッド実装のあるRubiniusもしくはJRubyの使用を強く勧めます。
Pumaはシンプルで、速くて、マルチスレッド、そして高い並列性を持ったRuby WebアプリケーションのためのHTTP1.1サーバです。 Rackをサポースするアプリケーションであれば、Pumaを利用でき、WebrickやMongrelの代用となります。 PumaはRubiuniusのためのgo-to serverとして設計されましたが、JRubyやMRI(CRuby/Matz' Ruby Implementation)でも動作します。 Pumaは、開発とプロダクション環境どちらにも使えます。
具体的には、Pumaは、リクエストをC-optimized Ragel extension(Mongrelから継承した)を使って処理します。 C-optimized Ragel extensionは、高速で、正確なHTTP1.1パースを手軽に行えます。 Pumaは、(コントロール可能な)内部スレッドプールから1つのスレッドを取り出し、あるリクエストを処理します。 つまり、Pumaは、あなたのWebアプリケーションに本当の並列性を提供します。
Rubinius 2.0を使うことで、Pumaは、あなたのCPUのすべてのコアを本当(VMでない?)のスレッドとして利用できます。 つまり、スループットの応じて複数のプロセスを立ち上げる必要がありません。 これは、JRubyでも同様の効果が得られます。
MRIにおいては、同時に1つのスレッドしか利用できないGlobal Interpreter Lock (GIL) があります。 しかし、(Twitterのような外部APIをHTTPで呼ぶような)ブロッキングIOが発生している間、Pumaは、ブロッキングIOを並列に行うことでMRIのスループットを向上させます。 (ThinのようなEventMachineベースのサーバではこの効果が無効になります。効果を得るには特別なライブラリを使う必要があります。) 実際はケースによって異なりますが、Pumaでベストなスループットを得るためには、RubiniusかJRubyのようなスレッドが利用できるRuby実装を使うことを強くオススメします。
PumaをRubyGemsからインストールします。
$ gem install puma
puma
コマンドがPATHに通っていれば、ルートフォルダで以下のようにしてRackアプリケーションを動かすことが出来ます。
$ puma app.ru
Puma3.0から、プラグイン機能をサポートしました。
開発を助ける謹製のプラグインとして、2つのプラグインがあります。
- tmp_restart
- tmp/restart.txt をtouchすることでサーバが再起動する
- heroku
- Herokuにデフォルト設定でPumaを使ってアップする
プラグインはPumaのコンフィグ(config/puma.rb
など)で、plugin "heroku"
のようにplugin "name"
で有効にできます。
プラグインは単純なPath指定によって有効にすることができます。例えばherokuプラグインの場合、require "puma/plugin/heroku"
と指定するだけです。これは、1つのGemで複数のプラグインを提供できようになっています。
tmp_restart
プラグインはPumaに同梱されています。
heroku
プラグインを利用する場合、puma-heroku
をgemからインストールしてください。
現在、プラグインは、start
とconfig
の2つのフックを利用できます。
start
は、サーバーの起動時に実行され、プラグインがPumaを補うために他の機能を開始できるようになります。
config
は、サーバーが構成されているときに実行され、構成を追加するために使用できるPuma::DSL
オブジェクトが渡されます。
Puma::Plugin
内の、パブリックメソッドをプラグインは利用することができます。
将来、もっと多くのフックとAPIがプラグインに提供される予定です。
WAFごとに起動方法、略
Pumaはサーバをコントロールする多くのオプションがあります。
詳しくはpuma -h
でhelpをみてください。
Pumaは設定可能な動的なスレッドプールを利用できます。
-t
フラグでプールするスレッドの最小数と最大数を設定できます。
$ puma -t 8:32
Pumaは、現在のトラフィック量にもとづいて、最小数から最大数の間で、スレッドの数を、自動で変更します。
現在のデフォルトは0:16
です。
自由に実験するしてください。
しかし、巨大な数の最大スレッド数には気をつけてください。
リソースを使い果たすかもしれません。
Puma2は、クラスターモードがあります。
リクエストを並列処理するために、スレッドに加えて、プロセスをフォークすることができます。
ワーカーの数は-w
フラグで指定できます。
$ puma -t 8:32 -w3
ネイティブスレッドを利用するRuby実装の場合、利用できるコアの数だけ指定するべきです。
ここで、クラスターモードであってもスレッドを利用されます。
-t
フラグで指定したスレッドはワーカーごとの数です。
つまり、-w 2 -t 16:16
は合計で32スレッドになります。
クラスターモードを利用する場合、ワーカーが立ち上がる前に、アプリケーションをプリロードすることができます。
これは、MRI Ruby 2.0で導入されたCopy on Write機能を利用するために必要です。
--preload
フラグをつけることで有効になります。
# CLI invocation
$ puma -t 8:32 -w 3 --preload
コンフィグファイルを使う場合、preload_app!
メソッドを使ってください。
コンフィグファイルは-C
フラグで指定できます。
$ puma -C config/puma.rb
# config/puma.rb
threads 8,32
workers 3
preload_app!
さらにコンフィグファイルで、ワーカー起動時の挙動を記述できます。
# config/puma.rb
on_worker_boot do
# configuration here
end
ここのコードは、アプリケーション起動前のセットアッププロセスに利用できます。 Puma特有の挙動をアプリケーション内に書く必要がなくなります。 例えば、ワーカー起動したことをログに残したり、statsdに情報を送ったりできます。 フックを追加するために、これを複数回呼び出すことができます。
もし、ActiveRecordを利用する状況でプリロードを使用するなら、コネクションプールをここに記載することをオススメします。
# config/puma.rb
on_worker_boot do
ActiveSupport.on_load(:active_record) do
ActiveRecord::Base.establish_connection
end
end
さらに、ワーカーがフォークされる前に実行されるブロックをコンフィグファイルに記述できます。
# config/puma.rb
before_fork do
# configuration here
end
ここのコードは、クライアントにフォークするまえに、クリーンアップするのに使うことができます。 Puma特有の挙動を記載することで、アプリケーションに余計なコードを書く必要がなくなります。
もし、ActiveRecordを利用する状況でプリロードを使用するなら、コネクションの切断をここに記載することで、コネクションリークを防ぐことができます。
# config/puma.rb
before_fork do
ActiveRecord::Base.connection_pool.disconnect!
end
このルールは、フレームワークが自動で起動する外部サービス(Redis, databases, memcache, ...)へのコネクションにも適用すべきです。
このプリロードを使う際、新しいコードはマスタープロセスに反映され、ワーカーにコピーされます。 (つまり、クラスターモードにのみ適用できます。) 一般的に、ワーカーがたびたび死し、すぐに起動する必要がある環境でプリロードを使うべきです。 もし、多くのワーカーが必要ないなら、プリロードを使うべきではありません。
プリロードは、段階的再始動(phased restart)と一緒に使うことは出来ません。 段階的再起動は、ワーカーを1つずつキルし、再起動します。 プリロードはすべてのマスターをノードをワーカーにコピーします。
もしPumaがアプリケーション外のエラーにあったとき、lowlevel_errorに定義されるようなメッセージとともにステータス500のエラーを返します。 この挙動をカスタマイズすることができます。 例えば、サードパーティのエラートラッキングサービスにレポートすることができます。 (rollbarの例)
lowlevel_error_handler do |e|
Rollbar.critical(e)
[500, {}, ["An error has occurred, and engineers have been informed. Please reload the page. If you continue to have problems, contact support@example.com\n"]]
end
複数のフラグが必要な他のサーバとは違い、PumaはBindingをシンプルなURIで指定できます。
$ puma -b tcp://127.0.0.1:9292
TCPの代わりに(5-10%パフォーマンスが上がる)UNIX Socketを利用したいですか?問題ありません!
$ puma -b unix:///var/run/puma.sock
UNIX Socketのパーミッションを変更したい場合は、umaskを追加します。
$ puma -b 'unix:///var/run/puma.sock?umask=0111'
セキュリティが必要な場合は、SSLソケットを使えます!
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert'
Pumaは、status/controlのアプリケーションをビルドインしています。 以下の例のようにコントロールサーバ起動できます。
$ puma --control tcp://127.0.0.1:9293 --control-token foo
この例では、Pumaはlocalhost:9293を直接リッスンするコントロールサーバを立ち上げます。
更に、コントロールサーバへのすべてのリクエストにはtoken=foo
をクエリストリングに付与する必要があります。
簡易的な認証です。
status.rbでどのようなことができるか確認できます。
コントロールサーバはpumactl
コマンドを受け付けます。
以下のコマンドPumaを再起動できます。
$ pumactl restart --control-token foo
pumactl
のオプションは、pumactl --help
をみてください。
-C
フラグで、コンフィグファイルを指定することができます。
$ puma -C /path/to/config
デフォルトでは、config/puma.rbを参照します。
環境特有のものを設定する場合、-e
と--environment
フラグを使用してください。
また、RACK_ENV環境変数を使用した場合、デフォルトのファイルの場所はconfig/puma/environment_name.rbになります。
もし、コンフィグファイルを使わないようにしたい場合、ダッシュを-C
フラグの引数に指定してください。
$ puma -C "-"
コンフィグファイルの詳細は、サンプルを見るか、実装を見てください。
Pumaは、アプリケーションのアップグレードを簡単に実行する仕組みを持っています。 利用可能な場合(MRI、Rubinius、JRuby)、Pumaはホットリスタートが可能です。 これは、unicornやnginxと同様に、サーバのソケットを開きっぱなしで実行できます。 これにより、リクエストを落とすことなく再起動することができます。
この再起動を実施するため、2つのビルドイン機能があります。
- pumaプロセスに
SIGUSR2
を送る。 - ステータスサーバに
/restart
のリクエストを送る。
現行とものと再起動後のものでコードの共有は行われません。 したがって、手でstop/startするのと変わりません。
もし新規プロセスがロードできなかった場合、プロセスはそのまま終了します。 したがって、プロダクション環境でPumaを使用する場合は、プロセスモニタ(下記参照)の下でPumaを実行する必要があります。
ホットリスタートは、サーバソケットを開き放しにすることで、デプロイの間のリクエストを落とすことなく、実施できます。 ただし、ホットリスタートは、新しいコードが完全に展開されていない間にリクエストが全くハングしないことを意味するものではありません もし、ゼロダウンタイムかつゼロハングを実現する場合は、段階的再起動(phased restart)を使うべきです。
pumactl phased-restart
を実行したとき、Pumaはワーカーを1つずつキルします。
つまり、少なくとも他のワーカーがリクエストを処理することができ、ゼロハングを実現できます。
しかし、アプリケーションのアップグレードには、データベーススキーマのアップグレードが必要な場合があります。 段階的再起動の場合、デプロイの間、新しいバージョンと古いバージョンが混在する時間ができます。 データベーススキーマのアップグレードは、古いバージョンへの後方互換があるように実施しなければいけません。
多くのデータベースマイグレーションがある場合は、段階的再起動ではなく、通常の再起動もしくはホットリスタートを実行すべきです。 この方法では、デプロイ中にコードを共有することはありません(この場合、preload_appはデプロイメントの迅速化に役立ちます)。
Pumaクラスタは以下のシグナルに反応します。
TTIN
- ワーカーの数を1増やす
TTOU
- ワーカーの数を1減らす
TERM
- ワーカーに
TERM
を送ることで、ワーカーは終了する
- ワーカーに
USR2
- ワーカーを再起動する
USR2
- ワーカーを階段的に再起動する。ローリングリスタート
HUP
stdout_redirect
設定値で定義されたログファイルを再オープンする
INT
- クラスタに
Ctrl-C
を送るのと同様。クラスタを終了する
- クラスタに
CHLD
詳細はこちら
共通のディレクトリにシンボルリンクでデプロイする場合(capistranoだと/current
)、
Pumaは、段階的再起動時に、設定なしでは変更を読みません。
Pumaのコンフィグファイルにワーキングディレクトリを明治する必要があります。
これは、古いPuma(2.15以前)から変更されました。
# config/puma.rb
directory '/var/www/current'
Pumaは、全てのアプリケーションのリソースが使用されているか知ることができません。
したがって、コンフィグファイルのon_restart
でフックすることができます。
on_restart
に渡されたブロックは、Pumaが再起動する直前に呼び出されます。
このブロック内にグローバルログファイル、redis接続などを閉じるコードを配置して、ファイルディスクリプタが再起動されたプロセスに漏れないようにする必要があります。
そうしないと、ゆっくりとディスクリプタが使い果たされ、サーバーが何度も再起動されると、最終的には不明瞭なクラッシュが発生します。
様々なプラットフォームで単一のものを実装することができないため、 Pumaは、異なるプラットフォームで次のような差異が発生します。
- JRuby、Windows:サーバソケットは再起動時にシームレスではないため、閉じて再オープンする必要があります。 これらのプラットフォームは、Rubyにさらされている新しいプロセスに記述子を渡す方法がありません
- JRuby、Windows:fork(2)がないためクラスタモードがサポートされていません。
- Windows:fork(2)がないためデーモンモードがサポートされていません。
pumactl
はシンプルなCLIツールで、上述したコントロールサーバへ接続します。
詳細はpumactl --help
で確認できます。
プロセスモニタもしくはスーパーバイザは、システム起動時にPumaの起動などを提供します。 systemdやupstartのようなモダンなプロセスモニタは、継続的な監視と再起動を提供し、プロダクション環境の生産性を向上させることができます。
- tool/jungle
- sysvinit upstart
- docs/systemd
使わないので略
Puma is copyright 2014 Evan Phoenix and contributors. It is licensed under the BSD 3-Clause license. See the included LICENSE file for details.