Puma adalah server HTTP 1.1 yang sederhana, cepat, multi-thread, dan sangat paralel untuk aplikasi Ruby/Rack .
Puma adalah server untuk aplikasi HTTP bertenaga Rack yang ditulis dalam Ruby. Dia:
Awalnya dirancang sebagai server untuk Rubinius, Puma juga bekerja dengan baik dengan Ruby (MRI) dan JRuby.
Pada MRI, terdapat Global VM Lock (GVL) yang memastikan hanya satu thread yang dapat menjalankan kode Ruby dalam satu waktu. Namun jika Anda melakukan banyak pemblokiran IO (seperti panggilan HTTP ke API eksternal seperti Twitter), Puma tetap meningkatkan throughput MRI dengan mengizinkan IO menunggu dilakukan secara paralel. Implementasi Ruby yang benar-benar paralel (TruffleRuby, JRuby) tidak memiliki batasan ini.
$ gem install puma
$ puma
Tanpa argumen, puma akan mencari file rackup (.ru) di direktori kerja bernama config.ru
.
Puma akan menginstal/mengkompilasi dengan dukungan untuk soket ssl, dengan asumsi file pengembangan OpenSSL diinstal pada sistem.
Jika sistem tidak menginstal file pengembangan OpenSSL, Puma akan menginstal/mengkompilasi, tetapi tidak mengizinkan koneksi ssl.
Puma adalah server default untuk Rails, termasuk dalam Gemfile yang dihasilkan.
Mulai server Anda dengan perintah rails
:
$ rails server
Banyak opsi konfigurasi dan fitur Puma tidak tersedia saat menggunakan rails server
. Disarankan agar Anda menggunakan executable Puma sebagai gantinya:
$ bundle exec puma
Anda dapat menjalankan aplikasi Sinatra dengan Puma dari baris perintah seperti ini:
$ ruby app.rb -s Puma
Namun, untuk benar-benar mengonfigurasi Puma menggunakan file konfigurasi, seperti puma.rb
, Anda perlu menggunakan puma
yang dapat dieksekusi. Untuk melakukan ini, Anda harus menambahkan file rak ke aplikasi Sinatra Anda:
# config.ru
require './app'
run Sinatra :: Application
Anda kemudian dapat memulai aplikasi Anda menggunakan:
$ bundle exec puma
Puma menyediakan banyak pilihan. Konsultasikan puma -h
(atau puma --help
) untuk daftar lengkap opsi CLI, atau lihat Puma::DSL
atau dsl.rb.
Anda juga dapat menemukan beberapa contoh konfigurasi sebagai bagian dari rangkaian pengujian.
Untuk tujuan debugging, Anda dapat mengatur variabel lingkungan PUMA_LOG_CONFIG
dengan nilai dan konfigurasi yang dimuat akan dicetak sebagai bagian dari proses boot.
Puma menggunakan kumpulan benang. Anda dapat mengatur jumlah minimum dan maksimum thread yang tersedia di kumpulan dengan tanda -t
(atau --threads
):
$ puma -t 8:32
Puma akan secara otomatis menskalakan jumlah thread, dari minimum hingga maksimum, berdasarkan berapa banyak lalu lintas yang ada. Default saat ini adalah 0:16
dan pada MRI adalah 0:5
. Jangan ragu untuk bereksperimen, namun berhati-hatilah untuk tidak mengatur jumlah thread maksimum ke jumlah yang besar, karena Anda dapat menghabiskan sumber daya pada sistem (atau menyebabkan perselisihan untuk Global VM Lock, saat menggunakan MRI).
Perlu diketahui bahwa Puma juga membuat thread sendiri untuk keperluan internal (misalnya menangani klien yang lambat). Jadi, meskipun Anda menentukan -t 1:1, diperkirakan sekitar 7 thread akan dibuat di aplikasi Anda.
Puma juga menawarkan "mode berkerumun". Pekerja fork
mode terkluster dari proses master. Setiap proses anak masih memiliki kumpulan threadnya sendiri. Anda dapat menyesuaikan jumlah pekerja dengan tanda -w
(atau --workers
):
$ puma -t 8:32 -w 3
Atau dengan variabel lingkungan WEB_CONCURRENCY
:
$ WEB_CONCURRENCY=3 puma -t 8:32
Perhatikan bahwa thread masih digunakan dalam mode berkerumun, dan pengaturan flag -t
thread adalah per pekerja, jadi -w 2 -t 16:16
akan menghasilkan total 32 thread, dengan 16 thread di setiap proses pekerja.
Jika variabel lingkungan WEB_CONCURRENCY
disetel ke "auto"
dan permata concurrent-ruby
tersedia di aplikasi Anda, Puma akan menyetel jumlah proses pekerja ke hasil prosesor yang tersedia.
Untuk diskusi mendalam tentang pengorbanan pengaturan thread dan jumlah proses, lihat dokumen kami.
Dalam mode berkerumun, Puma dapat "memuat" aplikasi Anda. Ini memuat semua kode aplikasi sebelum forking. Pramuat mengurangi total penggunaan memori aplikasi Anda melalui fitur sistem operasi yang disebut copy-on-write.
Jika variabel lingkungan WEB_CONCURRENCY
diatur ke nilai > 1 (dan --prune-bundler
belum ditentukan), pramuat akan diaktifkan secara default. Jika tidak, Anda dapat menggunakan flag --preload
dari baris perintah:
$ puma -w 3 --preload
Atau, jika Anda menggunakan file konfigurasi, Anda dapat menggunakan preload_app!
metode:
# config/puma.rb
workers 3
preload_app!
Pramuat tidak dapat digunakan dengan restart bertahap, karena restart bertahap mematikan dan memulai ulang pekerja satu per satu, dan pramuat menyalin kode master ke pekerja.
Saat menggunakan mode berkerumun, DSL konfigurasi Puma menyediakan kait before_fork
dan on_worker_boot
untuk menjalankan kode ketika proses master bercabang dan pekerja anak di-boot.
Disarankan untuk menggunakan kait ini dengan preload_app!
, jika tidak, konstanta yang dimuat oleh aplikasi Anda (seperti Rails
) tidak akan tersedia di dalam hook.
# config/puma.rb
before_fork do
# Add code to run inside the Puma master process before it forks a worker child.
end
on_worker_boot do
# Add code to run inside the Puma worker process after forking.
end
Selain itu, ada hook on_refork
yang hanya digunakan dalam mode fork_worker
, ketika proses anak pekerja 0 melakukan fork pada pekerja cucu:
on_refork do
# Used only when fork_worker mode is enabled. Add code to run inside the Puma worker 0
# child process before it forks a grandchild worker.
end
Yang penting, perhatikan pertimbangan berikut ketika Ruby melakukan fork pada proses anak:
SocketError
, Errno::EPIPE
, dan EOFError
.Oleh karena itu, kami merekomendasikan hal berikut:
before_fork
dan on_refork
untuk memutuskan koneksi soket induk saat melakukan forking, sehingga tidak disalin secara tidak sengaja ke proses anak.on_worker_boot
untuk memulai ulang thread latar belakang apa pun pada anak yang di-fork. DSL konfigurasi Puma menyediakan kait siklus hidup proses master on_booted
, on_restart
, dan on_stopped
yang dapat digunakan untuk menentukan blok kode yang akan dijalankan pada setiap peristiwa:
# config/puma.rb
on_booted do
# Add code to run in the Puma master process after it boots,
# and also after a phased restart completes.
end
on_restart do
# Add code to run in the Puma master process when it receives
# a restart command but before it restarts.
end
on_stopped do
# Add code to run in the Puma master process when it receives
# a stop command but before it shuts down.
end
Jika Puma menemukan kesalahan di luar konteks aplikasi Anda, Puma akan merespons dengan 400/500 dan pesan kesalahan tekstual sederhana (lihat Puma::Server#lowlevel_error
atau server.rb). Anda dapat menentukan perilaku khusus untuk skenario ini. Misalnya, Anda dapat melaporkan kesalahan tersebut ke layanan pelacakan kesalahan pihak ketiga (dalam contoh ini, rollbar):
lowlevel_error_handler do | e , env , status |
if status == 400
message = "The server could not process the request due to an error, such as an incorrectly typed URL, malformed syntax, or a URL that contains illegal characters. n "
else
message = "An error has occurred, and engineers have been informed. Please reload the page. If you continue to have problems, contact [email protected] n "
Rollbar . critical ( e )
end
[ status , { } , [ message ] ]
end
Ikat Puma ke soket dengan tanda -b
(atau --bind
):
$ puma -b tcp://127.0.0.1:9292
Untuk menggunakan Soket UNIX alih-alih TCP:
$ puma -b unix:///var/run/puma.sock
Jika Anda perlu mengubah izin soket UNIX, cukup tambahkan parameter umask:
$ puma -b 'unix:///var/run/puma.sock?umask=0111'
Butuh sedikit keamanan? Gunakan soket SSL:
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert'
localhost
, untuk penggunaan pengembangan): Puma mendukung permata localhost
untuk sertifikat yang ditandatangani sendiri. Hal ini sangat berguna jika Anda ingin menggunakan Puma dengan SSL secara lokal, dan sertifikat yang ditandatangani sendiri akan berfungsi untuk kasus penggunaan Anda. Saat ini, integrasi tersebut hanya dapat digunakan pada MRI.
Puma secara otomatis mengonfigurasi SSL ketika permata localhost
dimuat di lingkungan development
:
Tambahkan permata ke Gemfile Anda:
group ( :development ) do
gem 'localhost'
end
Dan memerlukannya secara implisit menggunakan bundler:
require "bundler"
Bundler . require ( :default , ENV [ "RACK_ENV" ] . to_sym )
Alternatifnya, Anda dapat meminta permata tersebut di file konfigurasi Anda, baik config/puma/development.rb
, config/puma.rb
, atau disetel melalui opsi -C
cli:
require 'localhost'
# configuration methods (from Puma::DSL) as needed
Selain itu, Puma harus mendengarkan soket SSL:
$ puma -b ' ssl://localhost:9292 ' -C config/use_local_host.rb
# The following options allow you to reach Puma over HTTP as well:
$ puma -b ssl://localhost:9292 -b tcp://localhost:9393 -C config/use_local_host.rb
Untuk menggunakan atau menghindari cipher SSL tertentu untuk TLSv1.2 dan di bawahnya, gunakan opsi ssl_cipher_filter
atau ssl_cipher_list
.
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&ssl_cipher_filter=!aNULL:AES+SHA'
$ puma -b 'ssl://127.0.0.1:9292?keystore=path_to_keystore&keystore-pass=keystore_password&ssl_cipher_list=TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA'
Untuk mengonfigurasi ciphersuites TLSv1.3 yang tersedia, gunakan opsi ssl_ciphersuites
(tidak tersedia untuk JRuby).
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&ssl_ciphersuites=TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256'
Lihat https://www.openssl.org/docs/man1.1.1/man1/ciphers.html untuk format filter sandi dan daftar lengkap rangkaian sandi.
Nonaktifkan TLS v1 dengan opsi no_tlsv1
:
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&no_tlsv1=true'
Untuk mengaktifkan tanda verifikasi yang ditawarkan oleh OpenSSL, gunakan verification_flags
(tidak tersedia untuk JRuby):
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&verification_flags=PARTIAL_CHAIN'
Anda juga dapat menyetel beberapa tanda verifikasi (dengan memisahkannya menggunakan koma):
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&verification_flags=PARTIAL_CHAIN,CRL_CHECK'
Daftar tanda yang tersedia: USE_CHECK_TIME
, CRL_CHECK
, CRL_CHECK_ALL
, IGNORE_CRITICAL
, X509_STRICT
, ALLOW_PROXY_CERTS
, POLICY_CHECK
, EXPLICIT_POLICY
, INHIBIT_ANY
, INHIBIT_MAP
, NOTIFY_POLICY
, EXTENDED_CRL_SUPPORT
, USE_DELTAS
, CHECK_SS_SIGNATURE
, TRUSTED_FIRST
, SUITEB_128_LOS_ONLY
, SUITEB_192_LOS
, SUITEB_128_LOS
, PARTIAL_CHAIN
, NO_ALT_CHAINS
, NO_CHECK_TIME
(lihat https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_hostflags.html#VERIFICATION-FLAGS).
Untuk mengaktifkan dekripsi runtime kunci SSL terenkripsi (tidak tersedia untuk JRuby), gunakan key_password_command
:
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&key_password_command=/path/to/command.sh'
key_password_command
harus:
Misalnya:
#! /bin/sh
echo " this is my password "
key_password_command
dapat digunakan dengan key
atau key_pem
. Jika kuncinya tidak dienkripsi, maka executable tidak akan dipanggil.
Puma memiliki aplikasi status dan kontrol bawaan yang dapat digunakan untuk menanyakan dan mengontrol Puma.
$ puma --control-url tcp://127.0.0.1:9293 --control-token foo
Puma akan memulai server kontrol pada port localhost 9293. Semua permintaan ke server kontrol harus menyertakan token kontrol (dalam hal ini, token=foo
) sebagai parameter kueri. Hal ini memungkinkan otentikasi sederhana. Periksa Puma::App::Status
atau status.rb untuk melihat aplikasi status apa yang tersedia.
Anda juga dapat berinteraksi dengan server kontrol melalui pumactl
. Perintah ini akan memulai ulang Puma:
$ pumactl --control-url 'tcp://127.0.0.1:9293' --control-token foo restart
Untuk melihat daftar opsi pumactl
, gunakan pumactl --help
.
Anda juga dapat menyediakan file konfigurasi dengan tanda -C
(atau --config
):
$ puma -C /path/to/config
Jika tidak ada file konfigurasi yang ditentukan, Puma akan mencari file konfigurasi di config/puma.rb
. Jika suatu lingkungan ditentukan (melalui flag --environment
atau melalui variabel lingkungan APP_ENV
, RACK_ENV
, atau RAILS_ENV
) Puma mencari file konfigurasi di config/puma/<environment_name>.rb
lalu kembali ke config/puma.rb
.
Jika Anda ingin mencegah Puma mencari file konfigurasi di lokasi tersebut, sertakan flag --no-config
:
$ puma --no-config
# or
$ puma -C "-"
Efek samping lain dari pengaturan lingkungan adalah apakah akan menampilkan jejak tumpukan (dalam development
atau test
), dan pengaturan RACK_ENV berpotensi memengaruhi middleware yang mencari nilai ini untuk mengubah perilakunya. Nilai default puma RACK_ENV adalah development
. Anda dapat melihat semua nilai default konfigurasi di Puma::Configuration#puma_default_options
atau konfigurasi.rb.
Periksa Puma::DSL
atau dsl.rb untuk melihat semua opsi yang tersedia.
Puma menyertakan kemampuan untuk memulai kembali sendiri. Jika tersedia (MRI, Rubinius, JRuby), Puma melakukan "hot restart". Ini adalah fungsi yang sama yang tersedia di Unicorn dan NGINX yang menjaga soket server tetap terbuka saat restart. Hal ini memastikan bahwa tidak ada permintaan tertunda yang dibatalkan saat restart berlangsung.
Untuk lebih lanjut, lihat dokumentasi Restart.
Puma merespons beberapa sinyal. Panduan terperinci untuk menggunakan sinyal UNIX dengan Puma dapat ditemukan di dokumentasi Signals.
Beberapa platform tidak mendukung semua fitur Puma.
Untuk MRI versi 2.2.7, 2.2.8, 2.2.9, 2.2.10, 2.3.4 dan 2.4.1, Anda mungkin melihat stream closed in another thread (IOError)
. Ini mungkin disebabkan oleh bug Ruby. Itu bisa diperbaiki dengan permata https://rubygems.org/gems/stopgap_13632:
if %w( 2.2.7 2.2.8 2.2.9 2.2.10 2.3.4 2.4.1 ) . include? RUBY_VERSION
begin
require 'stopgap_13632'
rescue LoadError
end
end
Puma mendukung Capistrano dengan permata eksternal.
Selain itu, Puma memiliki dukungan untuk daemonisasi bawaan melalui permata rubi puma-daemon. Permata ini memulihkan opsi daemonize
yang telah dihapus dari Puma mulai versi 5, tetapi hanya untuk MRI Ruby.
Merupakan hal yang umum untuk menggunakan monitor proses dengan Puma. Monitor proses modern seperti systemd atau rc.d menyediakan pemantauan berkelanjutan dan pengaktifan ulang untuk meningkatkan keandalan dalam lingkungan produksi:
Panduan komunitas:
Temukan detail untuk berkontribusi dalam panduan kontribusi.
Puma adalah hak cipta Evan Phoenix dan kontributor, berlisensi di bawah lisensi BSD 3-Clause. Lihat file LISENSI yang disertakan untuk detailnya.