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ã³ãã³ã
- pumactl
- ã³ã³ããã¼ã«ãµã¼ã
- ã³ãã³ã
- ãªãã·ã§ã³
- -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ã³ãã³ã
- çµå±ã©ãããã°ï¼
- ãã®ä»ã¡ã¢
- 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 [email protected]\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ããã¨ãªã¹ã¿ã¼ããã
- pumaã«ããã©ã«ãã§ã¤ãã¦ãã
- https://github.com/puma/puma/blob/master/lib/puma/plugin/tmp_restart.rb
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