Pumaの使い方 まとめ
- 感想
- スレッドベース
- railsへの導入
- 設定
- 参考URL
- 設定ファイルの読み込み
- 設定項目
- bind: バインド
- port: バインド(portとhost)
- ssl_bind: バインド(SSL)
- workers: ワーカー数
- threads: スレッド数のmin・max
- environment: 環境
- demonize: デーモン化
- pidfile: pidファイル置き場
- stdout_redirect: 標準出力/標準エラーを出力するファイル
- preload_app!: プリロード
- before_fork{}: 各ワーカーのフォーク前の処理
- on_worker_boot{}: 各ワーカーのboot前の処理
- prune_bundler: phased_restart時にbundlerのコンテキストを新しいものに切り替えてくれる
- plugin: プラグイン読み込み
- activate_control_app: コントロールサーバのURL
- state_path: stateファイルのパス
- directory: 起動ディレクトリ
- on_worker_shutdown: 各ワーカーのshutdown前の処理
- tag: プロセスリストでの追加情報
- worker_timeout: 全てのワーカーがマスタープロセスにチェックインする、タイムアウト時間
- worker_boot_timeout: ワーカーのブートのタイムアウト時間
- lowlevel_error_handler{}: アプリ外の例外のエラーハンドリング
- app: Rackアプリ
- rackup: アプリ起動ファイルのパス
- quiet: リクエストロギングをdisable
- log_requests: リクエストロギングをenable
- restart_command: pumaの再起動に使用するコマンド
- load: 追加のconfigファイルをロード
- on_restart{}: リスタート前の処理
- persistent_timeout: persistent connectionsのタイムアウト
- first_data_timeout: 受信無しでtcpソケットを開き続ける際のタイムアウト
- tcp_mode!: pumaをTCPモードで起動
- queue_requests: リクエストをキューする
- shutdown_debug: shutdown時にバックトレースを出力
- debug: デバグ情報を出力
- early_hints: Early Hintsのサポートを有効にする
- 他にも色々
- プロセス管理
- シグナル
- pumaコマンド
- オプション
- -C, --config PATH: 設定ファイル読み込み(loadに対応)
- -b, --bind URI: バインド(bindに対応)
- -t, --threads INT: スレッド数(threadsに対応)
- -w, --workers COUNT: workers数(workersに対応)
- -d, --daemon: デーモン化(daemonizeとquietに対応)
- -e, --environment ENVIRONMENT: 環境(environmentに対応)
- -p, --port PORT: bind(portに対応)
- -q, --quiet: リクエストロギングをdisable(quietに対応)
- -v, --log-requests: リクエストロギングをenable(log_requestsに対応)
- -R, --restart-cmd CMD: pumaの再起動に使用するコマンド(restart_commandに対応)
- -S, --state PATH:stateファイルのパス(state_pathに対応)
- --tcp-mode: TCPモード(tcp_mode!に対応)
- --early-hints: Early Hintsのサポートを有効にする(early_hintsに対応)
- --debug: デバグ情報を出力(debugに対応)
- --dir DIR: directory: 起動時ディレクトリ(directoryに対応)
- --pidfile PATH: PIDファイルパス(pidfileに対応)
- --preload: プリロード(preload_app!に対応)
- --prune-bundler: bundler切り替え(prune_bundlerに対応)
- --tag NAME: プロセスリストでの追加情報(tagに対応)
- --redirect-stdout FILE: 標準出力のリダイレクト先ファイル(stdout_redirectに対応)
- --redirect-stderr FILE, 標準エラー出力のリダイレクト先ファイル(stdout_redirectに対応)
- --[no-]redirect-append: 追記モード(stdout_redirectに対応)
- --control-url URL: コントロールサーバのurl(activate_control_appに対応)
- --control URL: --control-urlと同じ(activate_control_appに対応)
- --control-token TOKEN: コントロールサーバの認証用トークン(activate_control_appに対応)
- -I, --include PATH: $LOAD_PATHに追加
- -V, --version: バージョン
- -h --help: ヘルプ
- オプション
- pumactlコマンド
- railsコマンド
- 結局どうすれば?
- その他メモ
- puma関係のgem
- 自分用のメモを公開したものです。ドキュメント/ソースコード等をまとめただけで試していないコードも多いので、信頼性は低いです。
感想
- 新規にRailsアプリ作るならpuma使えば良さそう。でも、unicornやpassengerから乗り換えるほどではないかも(ケースバイケースだがパフォーマンスの顕著な差はないっぽい)
- Heroku使う場合はメモリ使用量が少なくて良さそう。メモリ500MBプランだとunicornで2worker動かすの辛かった記憶
スレッドベース
参考
- https://blog.willnet.in/entry/2015/02/24/155006
- http://railscasts.com/episodes/365-thread-safety?view=asciicast
- https://blog.yuuk.io/entry/2015-webserver-architecture
- http://d.hatena.ne.jp/naoya/20071010/1192040413
unicornはプロセスベース
- workerプロセスが2つあったら、2つのリクエストを同時に処理できる
- メリット
- シンプル(理解しやすい + コードが綺麗になりやすい)
- スレッドの知識がなくても安心
- スレッドセーフなコードを意識しなくても良い(普通にRailsアプリを書いていれば問題なさそうだけど、スレッドの知識が浅いので不安)
pumaはスレッドベース
- スレッドが2つあったら、2つのリクエストを同時に処理できる
- 実際には本番環境ではマルチプロセス + マルチスレッドで動かす(Clustered mode)。workerプロセスが2つ + スレッドが2つだったら、4つのリクエストを同時に処理できる
- ただし実際には、MRIではGILがあるため1プロセスで1スレッドしか実行されない
- メリット
- (MRIだとしても)IO時に別スレッドに処理させることができる
- スロークライアントの影響を受けにくい
- メモリ使用量が少ない(参考: http://puma.io/)
MRIのスレッド
- スレッドは複数持てるが、同時に実行できるスレッドは1つ。GIL(Global Interpreter Lock)のため。
- ただし、Bocking IO(ファイルIO、ネットワークIO等)になった際に、別のスレッドに切り替えて処理を進める。MRIでもスレッドベースの恩恵は部分的にある。
- IOはだいたい総時間の10~25%程度らしい(参考: https://techracho.bpsinc.jp/hachi8833/2017_11_13/47696)
Jruby・Rubiniusのスレッド
- スレッドをフルに使える
- pumaにはJrubyやWindows特有の成約がいくつかある(別項目)
- MRI以外使うことはないかなー
スロークライアント
- 回線の遅いクライアント(3Gのモバイル端末など)
- Pumaはスレッドベースなので、IOの際に(MRIだとしても)別のスレッドに処理をさせることができる。なのでネットワークIOが長いスロークライアントには都合がよい
railsへの導入
# Gemfile gem 'puma'
$ bundle install
# 起動 # $ rails s Puma $ rails s
設定
参考URL
- https://github.com/puma/puma/blob/master/lib/puma/dsl.rb
- https://github.com/puma/puma/blob/master/examples/config.rb
設定ファイルの読み込み
- 3つの起動コマンド(
rails s
、pumactl start
、puma
)は、以下の設定ファイルを自動で読み込む- 環境指定がない場合: config/puma.rb
- 環境指定がある場合: config/puma/<environment_name>.rb
pumactl -F config/puma.rb start
のように、オプションで指定することも可能
設定項目
bind: バインド
- URI指定しかないので、シンプル
- デフォルト: "tcp://0.0.0.0:9292"
# TCPソケットを使う場合 bind 'tcp://0.0.0.0:9292' # UNIXソケットを使う場合 # TCPより若干パフォーマンスが上がる(場合がある) bind 'unix:///var/run/puma.sock' # UNIXソケットのパーミッションを変更する必要がある場合、umaskパラメーターを利用する bind 'unix:///var/run/puma.sock?umask=0111' # SSLを利用する場合 bind 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert'
port: バインド(portとhost)
- bind使えばok
# bind 'tcp://0.0.0.0:9292' と同じ port '9292', '0.0.0.0'
ssl_bind: バインド(SSL)
- bind使えばok
# bind 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert' と同じ ssl_bind '127.0.0.1', '9292', { key: path_to_key, cert: path_to_cert }
workers: ワーカー数
- ワーカー数を指定するとclustered modeになる
- master processからworkerをforkする
- workerプロセスはそれぞれスレッドプールを持つ
- デフォルト: 0
# ワーカー2スレッド16の場合、スレッドは合計で32になる workers 2
threads: スレッド数のmin・max
- プールで利用できるスレッドの数
- スレッド数はtrafficによって自動で増減する
- maxを大きくしすぎるとマシンリソースを食いつくしてしまう可能性があるので、注意
- ここで指定したスレッド以外にも、スロークライアントの処理等のpuma自体の内部的な処理にもスレッドが作られるので注意。なので
-t 1:1
で指定しても、実際には7スレッドくらいが作成される。 - デフォルト: 0:16
threads 16, 16
environment: 環境
- デフォルト: "development"
environment 'production' environment ENV.fetch("RAILS_ENV") { "development" } # railsで使う場合は、環境変数RAILS_ENVを使うのが良さげ
demonize: デーモン化
- デフォルト: false
- pidfile、stdout_redirectと一緒に使う
daemonize true
pidfile: pidファイル置き場
pidfile '/u/apps/lolcat/tmp/pids/puma.pid' pidfile "#{Dir.pwd}/tmp/pids/puma.pid" # Railsの場合、tmp/pids/puma.pidに置くと良さげ
stdout_redirect: 標準出力/標準エラーを出力するファイル
- 第三引数は追記モード
stdout_redirect '/u/apps/lolcat/log/stdout', '/u/apps/lolcat/log/stderr' stdout_redirect '/u/apps/lolcat/log/stdout', '/u/apps/lolcat/log/stderr', true
preload_app!: プリロード
- 全てのアプリコードをfork前にロードする。これによりRuby 2.0+の場合、OSのcopy-on-writeが効く。そのためメモリ使用量が下がる
- Cluster modeでしか使えない
- phased-restartとpreloadは同時には使えない
preload_app!
before_fork{}: 各ワーカーのフォーク前の処理
- preload_app!時に、DBやredisのコネクションを閉じるのに使う -> 不要?(参考: https://paulownia.hatenablog.com/entry/2018/08/13/211856)
before_fork do ActiveRecord::Base.connection_pool.disconnect! end
on_worker_boot{}: 各ワーカーのboot前の処理
- ブート前のセットアップはここで行う
- アプリ固有ではなく、puma固有の処理はここで行う
- DB接続はここでやっておく
on_worker_boot do ActiveSupport.on_load(:active_record) do ActiveRecord::Base.establish_connection end end
prune_bundler: phased_restart時にbundlerのコンテキストを新しいものに切り替えてくれる
- これによりphased_restart(1つずつ再起動)した時に最新のGemfileを見に行ってくれる
- phased_restartを行いたい時にほぼ必須のオプション
- デフォルト: off
prune_bundler
plugin: プラグイン読み込み
plugin :tmp_restart
activate_control_app: コントロールサーバのURL
- pumactlコマンドでpumaを操作するのに利用する
- 詳しくは コントロールサーバ を参照
# デフォルト: localhostのport 9293 activate_control_app # unixソケット activate_control_app 'unix:///var/run/pumactl.sock' # tokenによる認証 # トークンを指定すると、クエリパラメータにそのトークンを指定しなければいけなくなる activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' } activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }
state_path: stateファイルのパス
- stateファイルはサーバの状態の情報
- pumactlコマンドでpumaを操作するのに利用する
state_path '/u/apps/lolcat/tmp/pids/puma.state' state_path "#{Dir.pwd}/tmp/pids/puma.state" # Railsの場合、tmp/pids/puma.stateかな
directory: 起動ディレクトリ
- defalut: カレントディレクトリ
directory '/u/apps/lolcat'
on_worker_shutdown: 各ワーカーのshutdown前の処理
on_worker_shutdown do puts 'On worker shutdown...' end
tag: プロセスリストでの追加情報
- tagを指定しない場合は、推測する
- tagを追加したくない場合は、空文字を指定する
tag 'app name'
worker_timeout: 全てのワーカーがマスタープロセスにチェックインする、タイムアウト時間
- タイムアウトしたら、workerはリスタートされる
- デフォルト: 60秒
worker_timeout 60
worker_boot_timeout: ワーカーのブートのタイムアウト時間
- デフォルト: worker_timeoutの値
worker_boot_timeout 60
lowlevel_error_handler{}: アプリ外の例外のエラーハンドリング
- デフォルト: 500とエラーテキストを返す
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
app: Rackアプリ
- config自体がRackアプリになる
app do |env| puts env body = 'Hello, World!' [200, { 'Content-Type' => 'text/plain', 'Content-Length' => body.length.to_s }, [body]] end
rackup: アプリ起動ファイルのパス
- デフォルト: "config.ru"
rackup '/u/apps/lolcat/config.ru'
quiet: リクエストロギングをdisable
- デフォルト: false
quiet
log_requests: リクエストロギングをenable
restart_command: pumaの再起動に使用するコマンド
restart_command '/u/app/lolcat/bin/restart_puma'
load: 追加のconfigファイルをロード
on_restart{}: リスタート前の処理
- 例: ログファイルを閉じる、DBコネクションを閉じる、Redisコネクションを閉じる
on_restart do puts 'On restart...' end
persistent_timeout: persistent connectionsのタイムアウト
first_data_timeout: 受信無しでtcpソケットを開き続ける際のタイムアウト
tcp_mode!: pumaをTCPモードで起動
queue_requests: リクエストをキューする
- リクエストをキューすることで、一般的にはパフォーマンスが上がる
- 参考: https://github.com/puma/puma/blob/master/docs/architecture.md
- デフォルト: true
shutdown_debug: shutdown時にバックトレースを出力
debug: デバグ情報を出力
early_hints: Early Hintsのサポートを有効にする
他にも色々
プロセス管理
シグナル
- masterプロセスにシグナルを送ることで、pumaの停止/再起動等が可能
- pumactlコマンドがいい感じにラップしてくれてるので、そっちを使うのが良さそう
シグナル一覧
INT: 停止
- Ctrl+C
QUIT: 停止
TERM: 停止
USR2: 再起動
- 設定ファイルをリロードする
USR1: 再起動(Phased Restart)
- 設定ファイルをリロードしない
TTIN: ワーカー1増やす
TTOU: ワーカー1減らす
HUP: ログファイルをリオープン
- ログファイルは
stdout_redirect
の設定を見る stdout_redirect
がなければINTのようにふるまう
pumaコマンド
- pumaコマンドのオプションは設定ファイルに対応する項目がある。詳細については 設定項目 を参照
- ただし設定ファイルとは設定方法が微妙に違う項目もあるので注意
オプション
-C, --config PATH: 設定ファイル読み込み(loadに対応)
# デフォルト値(config/puma.rb) $ puma # 指定 $ puma -C config/puma.rb # ファイルを指定したくない場合(デフォルト値が使われるのを防ぐ) $ puma -C "-"
-b, --bind URI: バインド(bindに対応)
# TCPソケットを使う場合 $ puma -b tcp://127.0.0.1:9292 # UNIXソケットを使う場合 # TCPより若干パフォーマンスが上がる(場合がある) $ puma -b unix:///var/run/puma.sock # UNIXソケットのパーミッションを変更する必要がある場合、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'
-t, --threads INT: スレッド数(threadsに対応)
$ puma -t 8:32
-w, --workers COUNT: workers数(workersに対応)
$ puma -w 3
-d, --daemon: デーモン化(daemonizeとquietに対応)
-e, --environment ENVIRONMENT: 環境(environmentに対応)
-p, --port PORT: bind(portに対応)
-q, --quiet: リクエストロギングをdisable(quietに対応)
-v, --log-requests: リクエストロギングをenable(log_requestsに対応)
-R, --restart-cmd CMD: pumaの再起動に使用するコマンド(restart_commandに対応)
-S, --state PATH:stateファイルのパス(state_pathに対応)
--tcp-mode: TCPモード(tcp_mode!に対応)
--early-hints: Early Hintsのサポートを有効にする(early_hintsに対応)
--debug: デバグ情報を出力(debugに対応)
--dir DIR: directory: 起動時ディレクトリ(directoryに対応)
--pidfile PATH: PIDファイルパス(pidfileに対応)
--preload: プリロード(preload_app!に対応)
--prune-bundler: bundler切り替え(prune_bundlerに対応)
--tag NAME: プロセスリストでの追加情報(tagに対応)
--redirect-stdout FILE: 標準出力のリダイレクト先ファイル(stdout_redirectに対応)
--redirect-stderr FILE, 標準エラー出力のリダイレクト先ファイル(stdout_redirectに対応)
--[no-]redirect-append: 追記モード(stdout_redirectに対応)
--control-url URL: コントロールサーバのurl(activate_control_appに対応)
# pumaの場合 $ puma --control-url tcp://127.0.0.1:9293 --control-token foo # pumactlの場合 $ pumactl --control-url 'tcp://127.0.0.1:9293' --control-token foo restart
--control URL: --control-urlと同じ(activate_control_appに対応)
--control-token TOKEN: コントロールサーバの認証用トークン(activate_control_appに対応)
-I, --include PATH: $LOAD_PATHに追加
-V, --version: バージョン
-h --help: ヘルプ
pumactlコマンド
pumactl
- コントロールサーバを使ってpumaのプロセス管理を行うコマンド
- コントロールサーバのurlが指定されている場合は、HTTPリクエストを使う。urlが指定されていない場合は、シグナルを使う。
- url指定は、設定なら
activate_control_app
、オプションなら--control-url
- ctlはcontrolの略なんだね
- pumactlのメリット
- pumaのプロセス管理はpumaコマンド(起動/状態確認など)、シグナル(停止/再起動など)、PID/stateファイル管理などで色々面倒だった。pumactlコマンドでプロセス管理の統一的なインタフェースを用意したってことらしい。(参考: http://ruby-journal.com/digesting-pumactl/)
- 参考: https://github.com/puma/puma/blob/master/lib/puma/control_cli.rb
コントロールサーバ
- HTTPリクエスト受け付けて、pumaの再起動などを行うRackアプリのサーバ
- HTTPリクエストを送るにはpumactlコマンドを使う
- tokenを使えば簡易的な認証が可能
- 使い方
- 設定ファイルなら
activate_control_app
- pumaコマンドなら
--control-url
- 設定ファイルなら
- 参考: https://github.com/puma/puma/blob/master/lib/puma/app/status.rb
# puma + コントロールサーバ 起動 $ puma --control-url tcp://127.0.0.1:9293 --control-token foo # HTTPリクエストでpuma再起動 $ pumactl --control-url 'tcp://127.0.0.1:9293' --control-token foo restart
コマンド
start: 起動
$ pumactl start
stop: 停止(TERM)
$ pumactl stop
halt: 停止(QUIT)
# $ kill -QUIT `(cat tmp/pids/server.pid)` 相当
$ pumactl halt
restart: 再起動(USR2)
$ pumactl restart
phased-restart: 再起動(USR1)
- phased-restart
$ pumactl phased-restart
status: PID確認
$ pumactl status # 起動している場合 PID 2557 is running # 起動してない場合 No puma process
stats: worker等の情報
gc: ガベージコレクション開始
gc-stats: ガベージコレクションの情報
reload-worker-directory: ?
オプション
-S, --state PATH: stateファイルのパス
-F, --config-file PATH: 設定ファイルのパス
-P, --pidfile PATH: pidファイルのパス
-p, --pid PID: pid
-C, --control-url URL: control serverのurl
-T, --control-token TOKEN: control serverの認証トークン
-H, --help: ヘルプ表示
-V, --version: バージョン表示
-Q, --quiet: 表示を止める
railsコマンド
起動
$ rails s $ rails s Puma
結局どうすれば?
- 設定は全て設定ファイルに書いて、pumactlコマンド使うのが簡単そう。
その他メモ
2つのモード
Single mode: プロセスは1つだけ
- もともとはpumaはSingle modeのみでスレッド専用として開発された
Clustered mode: masterプロセス1つ + workerプロセス複数
- master-workerモデル
- 設定でworkersを指定するとこっちになる
- 本番環境ではClustered modeで使うべき
2つのリスタート
参考
Hot Restart: リスタート時に、サーバーのソケットを開きっぱなしにする
- 処理が完了するのを待ってから再起動する
- unicornとかのホットデプロイとは違うっぽい(ダウンタイムなしという意味ではPhased Restartが近い?)
メリット
- リクエストの取りこぼしがなくなる
- preloadと併用できる
デメリット
- ダウンタイムあり(リスタートが完了するまで、リクエスト処理は止まる)
使い方
- pumactl restart
- USR2シグナル
Phased Restart: 1つずつworkerを再起動する
- ワーカーを1つずつ再起動するので、どこかのワーカーがリクエスト処理をしてくれる
メリット
- ダウンタイムなし(常にどこかのworkerが生きているので、リクエスト処理が止まらない)
デメリット
- Clustered mode(復数worker)のみ
- preloadは使えない(workerを1つずつkillして、1つずつ再起動するため)
- DBスキーマは新しいのに、アプリコードは古いという自体になりうる(新しいコードと古いコードが共存するので)。なのでマイグレーションをするような環境ではHOT Restartを利用すべき。あるいは古いバージョンのアプリコードと互換性がないといけない。
使い方
- pumactl phased-restart
- USR1シグナル
プラグイン
- Pumaに機能を追加できる
- Puma3.0から導入
使い方
# Gemfile gem 'puma-heroku' # プラグイン
$ bundle install
# config/puma.rb plugin :heroku
有名プラグイン
tmp_restart: tmp/restart.txtをtouchするとリスタートする
heroku: heroku向けの設定を用意してくれる
puma-heroku
という別のgem- https://github.com/puma/puma-heroku/blob/master/lib/puma/plugin/heroku.rb
自分で実装
- configやstart等のフックメソッドをオーバーライドすれば実装できるっぽい
- 上の2つのプラグインを参考にする
worker数、thread数の目安
- 参考
worker数の目安
- CPUの観点
- とりあえずworker数 = CPUコア数。実際にはさらに最適化すべき。コア数以上にしたほうが良い場合もある。CPUコア数の1.5倍まで増やしてもいいかも
- cpu使用率70%くらいが目安
- メモリの観点
- worker数 = RAM / (1プロセスのメモリ使用量 * 1.2) # Railsアプリだと1プロセス200MB~400MB程度が基準
- メモリ使用量70%くらいが目安
- ロードバランシングの観点
- 最適なロードバランシングのためにはworker数は3以上
thread数の目安
- thread数決めるのは難しい。5程度にして後は忘れるのがいいという意見も。
- デフォは16。これはそこそこ妥当らしい。
- ちなみにMRIの場合はIOだけ並列化可能。これはだいたい総時間の10~25%程度らしい
- Unicornから移行する場合
- workerをunicornの半分にする + thread数を2にする -> これでメモリ使用量が50%になる
- スレッドに慣れてきたら、workerを減らしてthreadを増やして調整すると良い
puma + Systemd
- 本番環境ではSystemd使うと便利
- 参考
puma + Nginx
puma + heroku
- herokuのオススメサーバはpuma
- herokuはリバースプロキシがない。なので特にherokuではpumaが良さそう
- メモリが500MBの場合だと、unicornではきつかった記憶
- 参考
Rails5からRailsのデフォルト
- Rails5でActionCableの導入に伴い、development環境のアプリケーションサーバがWebrickからpumaへ変更
Mongrelから派生
- pumaはMongrelから派生した
- 改善点
- Rackアプリにした
- スレッドベースにした
プラットフォームによる成約
JRuby, Windows
restart時にソケットを必ず閉じる
ディスクリプタを受けわたせないため
cluster modeがない
fork(2)がないため
Windows
daemon modeがない
fork(2)がないため
puma関係のgem
puma_worker_killer: 定期的にworkerをkillするgem
- workerを長時間放置しておくと、メモリ使用量が徐々に増えてきて、サーバ全体の処理が遅くなる可能性がある。 -> puma_worker_killerを使い、定期的にworkerをkillして新しいworkerを立ち上げる
- Ruby Webアプリのプロセスは時間とともにメモリ使用量が増加する。生成後の2倍から3倍に達することもある。
- unicorn_worker_killerのpuma版
- 当然cluster modeでしか使えない
導入
1. インストール
# Gemfile gem 'puma_worker_killer'
$ bundle install
2. 設定
# config/puma.rb before_fork do PumaWorkerKiller.config do |config| # サーバのメモリ(1024MB) config.ram = 1024 # 確認頻度(5秒毎) config.frequency = 5 # workerを再起動する閾値(メモリ使用量が65%になったらkill) # 一番メモリ使用量の多いworkerを再起動する config.percent_usage = 0.65 # rolling_restartの頻度(12時間に1回) # rolling_restart: メモリ使用量に関係なく、順番にworkerを再起動する仕組み config.rolling_restart_frequency = 12 * 3600 # falseにすると監視ログを止める # 普通のログに混ざって紛らわしい config.reaper_status_logs = true end PumaWorkerKiller.start end
puma-dev: powのpuma版
- powのpuma版。powと同等の機能が利用できる
- 開発時のサーバとして利用すると便利
対応OS
- OS X
- Linux
powの知識
pros
- シンボリックリンクを貼るだけでバーチャルホストで切って開発できる
- "rails s"で起動することなく、アクセスすると自動で起動する
- 同一LAN内からアクセス可能
- 設定が不要(Zero-configuration)
cons
- もうメンテされていない
- 起動が遅い
- フォアグラウンドじゃないのでbinding.pryできない(pry-remoteやプロキシ使えばいける)
使い方
# ローカルからアクセス http://[project名].dev/ # 同一LAN内からアクセス http://[project名].[LANのIP-ADDRESS].xip.io
xip.io: IPアドレスをサブドメインに与えることでIPアドレス自身を返す、グローバルなDNS
- 37signalsがpowのために作ったらしい
- puma-devもxip.ioを利用できる
ワイルドカードDNS
- IPアドレスをサブドメインに与えることで、IPアドレス自身を返す、グローバルなDNS
- 例: "192.168.100.200.wild.card" は "192.168.100.200" を返す
powよりpuma-devを使うべき
- powがメンテされていない
- https対応
- WebSocket対応
- powder(pow用のコマンドツール)相当の機能が付属している
- MacとLinuxをサポート
導入(mac)
0. powをインストール済みの場合は、アンインストールする
- 色々問題があるっぽい
$ curl get.pow.cx/uninstall.sh | sh
1. brewでインストール
- gemでも可能
$ brew install puma/puma/puma-dev
2. DNS設定
- resolverを使い、ローカルのMacにpuma-dev用のDNSサーバ設定を追加
$ sudo puma-dev -setup
3. セットアップ
- ".dev"ではなく".test"にする
$ puma-dev -install -d test
4. シンボリックリンクを貼る
# puma-devコマンドを使う場合 $ cd my_app $ puma-dev link -n my_app # 自分でシンボリックリンク貼ってもokらしい $ cd ~/.puma-dev/ $ ln -s my_app
5. リスタート
touch tmp/restart.txt
デフォルトの設定
port: 80と443
domain: .test
- 昔は.devドメインだったが、2017年にGoogleが所有してからHSTS onlyになってしまったため、.testに変わった
- ChromeのVer.63から、.devにはHTTPSが必須
コマンド
puma-dev link: シンボリックリンクを貼る
# puma-devコマンドを使う場合 $ cd my_app $ puma-dev link -n my_app # 自分でシンボリックリンク貼ってもokらしい $ cd ~/.puma-dev/ $ ln -s my_app
touch tmp/restart.txt: アプリ再起動
puma-dev -stop: 全アプリを再起動
- puma-devにUSR1シグナルを送っている
# これと同じ $ pkill -USR1 puma-dev
puma-dev: 起動(フォアグラウンド)
- ~/.puma-devを使う
puma-dev -h: ヘルプ
sudo puma-dev -setup: 設定(macのみ)
puma-dev -pow: ~/.powを使う
- By default, puma-dev uses the domain .test to manage your apps. If you want to have puma-dev look for apps in ~/.pow, just run puma-dev -pow.
環境変数
環境変数一覧
CONFIG: pumaの設定ファイルのパス
- デフォルト: なし
- config/puma-dev.rbとかを指定する
THREADS: pumaのスレッド数
- デフォルト: 5
WORKERS: pumaのworker数
- デフォルト: 0
環境変数の読み込み順(上から順)
- ~/.powconfig
- .env
- .powrc
- .powenv
シンボリックリンク
- "~/.puma-dev/"配下にサブディレクトリを置けば、使える
- cool-frontend.testの場合、以下の2つを探す
- ~/.puma-dev/cool-frontend
- ~/.puma-dev/cool/frontend
HTTPS
- デフォルトでport443を使う
- 自動でオレオレ証明書を作ってくれるっぽい: "~/Library/Application Support/io.puma.dev/cert.pem."
ログ
- ログのパス: ~/Library/Logs/puma-dev.log