Puma ist ein einfacher, schneller, multithreadfähiger und hochparalleler HTTP 1.1-Server für Ruby/Rack-Anwendungen .
Puma ist ein in Ruby geschriebener Server für Rack-basierte HTTP-Anwendungen. Es ist:
Ursprünglich als Server für Rubinius konzipiert, funktioniert Puma auch gut mit Ruby (MRI) und JRuby.
Bei MRI gibt es eine globale VM-Sperre (GVL), die sicherstellt, dass jeweils nur ein Thread Ruby-Code ausführen kann. Wenn Sie jedoch viele blockierende E/A-Vorgänge ausführen (z. B. HTTP-Aufrufe an externe APIs wie Twitter), verbessert Puma dennoch den Durchsatz von MRI, indem E/A-Wartevorgänge parallel ausgeführt werden können. Wirklich parallele Ruby-Implementierungen (TruffleRuby, JRuby) unterliegen dieser Einschränkung nicht.
$ gem install puma
$ puma
Ohne Argumente sucht Puma im Arbeitsverzeichnis mit dem Namen config.ru
nach einer Rackup-Datei (.ru).
Puma wird mit Unterstützung für SSL-Sockets installieren/kompilieren, vorausgesetzt, OpenSSL-Entwicklungsdateien sind auf dem System installiert.
Wenn auf dem System keine OpenSSL-Entwicklungsdateien installiert sind, führt Puma die Installation/Kompilierung durch, lässt jedoch keine SSL-Verbindungen zu.
Puma ist der Standardserver für Rails, der in der generierten Gemfile enthalten ist.
Starten Sie Ihren Server mit dem rails
-Befehl:
$ rails server
Viele Konfigurationsoptionen und Puma-Funktionen sind bei Verwendung rails server
nicht verfügbar. Es wird empfohlen, stattdessen die ausführbare Datei von Puma zu verwenden:
$ bundle exec puma
Sie können Ihre Sinatra-Anwendung mit Puma wie folgt über die Befehlszeile ausführen:
$ ruby app.rb -s Puma
Um Puma jedoch tatsächlich mithilfe einer Konfigurationsdatei wie puma.rb
zu konfigurieren, müssen Sie die ausführbare Datei puma
verwenden. Dazu müssen Sie Ihrer Sinatra-App eine Rackup-Datei hinzufügen:
# config.ru
require './app'
run Sinatra :: Application
Anschließend können Sie Ihre Bewerbung starten mit:
$ bundle exec puma
Puma bietet zahlreiche Optionen. Eine vollständige Liste der CLI-Optionen finden Sie unter puma -h
(oder puma --help
) oder unter Puma::DSL
oder dsl.rb.
Im Rahmen der Testsuite finden Sie auch mehrere Konfigurationsbeispiele.
Zu Debugging-Zwecken können Sie die Umgebungsvariable PUMA_LOG_CONFIG
mit einem Wert setzen und die geladene Konfiguration wird als Teil des Bootvorgangs gedruckt.
Puma verwendet einen Thread-Pool. Mit dem Flag -t
(oder --threads
) können Sie die minimale und maximale Anzahl der im Pool verfügbaren Threads festlegen:
$ puma -t 8:32
Puma skaliert die Anzahl der Threads automatisch vom Minimum bis zum Maximum, je nachdem, wie viel Traffic vorhanden ist. Der aktuelle Standardwert ist 0:16
und bei der MRT beträgt er 0:5
. Experimentieren Sie ruhig, aber achten Sie darauf, die Anzahl der maximalen Threads nicht zu hoch festzulegen, da sonst die Ressourcen auf dem System erschöpft werden könnten (oder es zu Konflikten um die globale VM-Sperre kommen könnte, wenn Sie MRI verwenden).
Beachten Sie, dass Puma zusätzlich eigene Threads für interne Zwecke erstellt (z. B. Handhabung langsamer Clients). Selbst wenn Sie also -t 1:1 angeben, müssen Sie damit rechnen, dass in Ihrer Anwendung etwa 7 Threads erstellt werden.
Puma bietet auch den „Clustered-Modus“ an. Der Clustermodus fork
die Worker eines Masterprozesses. Jeder untergeordnete Prozess verfügt weiterhin über einen eigenen Thread-Pool. Sie können die Anzahl der Arbeiter mit dem Flag -w
(oder --workers
) optimieren:
$ puma -t 8:32 -w 3
Oder mit der Umgebungsvariablen WEB_CONCURRENCY
:
$ WEB_CONCURRENCY=3 puma -t 8:32
Beachten Sie, dass Threads immer noch im Cluster-Modus verwendet werden und die Thread-Flag-Einstellung -t
pro Worker gilt, sodass mit -w 2 -t 16:16
insgesamt 32 Threads erzeugt werden, davon 16 in jedem Worker-Prozess.
Wenn die Umgebungsvariable WEB_CONCURRENCY
auf "auto"
gesetzt ist und das concurrent-ruby
Gem in Ihrer Anwendung verfügbar ist, setzt Puma die Anzahl der Worker-Prozesse auf das Ergebnis der verfügbaren Prozessoren.
Eine ausführliche Diskussion der Kompromisse zwischen Thread- und Prozessanzahleinstellungen finden Sie in unseren Dokumenten.
Im Cluster-Modus kann Puma Ihre Anwendung „vorab laden“. Dadurch wird der gesamte Anwendungscode vor dem Forken geladen. Durch das Vorladen wird die Gesamtspeichernutzung Ihrer Anwendung über eine Betriebssystemfunktion namens „Copy-on-Write“ reduziert.
Wenn die Umgebungsvariable WEB_CONCURRENCY
auf einen Wert > 1 gesetzt ist (und --prune-bundler
nicht angegeben wurde), ist das Vorladen standardmäßig aktiviert. Andernfalls können Sie das Flag --preload
über die Befehlszeile verwenden:
$ puma -w 3 --preload
Wenn Sie eine Konfigurationsdatei verwenden, können Sie auch preload_app!
Verfahren:
# config/puma.rb
workers 3
preload_app!
Das Vorladen kann nicht mit einem phasenweisen Neustart verwendet werden, da der phasenweise Neustart Worker nacheinander tötet und neu startet und das Vorladen den Code des Masters in die Worker kopiert.
Bei Verwendung des Cluster-Modus stellt Pumas Konfigurations-DSL die Hooks before_fork
und on_worker_boot
bereit, um Code auszuführen, wenn die Master-Prozess-Forks bzw. die untergeordneten Worker gebootet werden.
Es wird empfohlen, diese Hooks mit preload_app!
, andernfalls sind von Ihrer Anwendung geladene Konstanten (z. B. Rails
) in den Hooks nicht verfügbar.
# 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
Darüber hinaus gibt es einen on_refork
-Hook, der nur im fork_worker
Modus verwendet wird, wenn der untergeordnete Worker-0-Prozess einen untergeordneten Worker forkt:
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
Beachten Sie unbedingt die folgenden Überlegungen, wenn Ruby einen untergeordneten Prozess verzweigt:
SocketError
, Errno::EPIPE
und EOFError
.Daher empfehlen wir Folgendes:
before_fork
und on_refork
um die Socket-Verbindungen des übergeordneten Prozesses beim Forken zu trennen, damit sie nicht versehentlich in den untergeordneten Prozess kopiert werden.on_worker_boot
, um alle Hintergrundthreads auf dem gegabelten untergeordneten Element neu zu starten. Pumas Konfigurations-DSL bietet Master-Prozess-Lebenszyklus-Hooks on_booted
, on_restart
und on_stopped
, die verwendet werden können, um Codeblöcke anzugeben, die bei jedem Ereignis ausgeführt werden sollen:
# 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
Wenn Puma außerhalb des Kontexts Ihrer Anwendung auf einen Fehler stößt, antwortet es mit einer 400/500 und einer einfachen Textfehlermeldung (siehe Puma::Server#lowlevel_error
oder server.rb). Sie können für dieses Szenario ein benutzerdefiniertes Verhalten festlegen. Sie können den Fehler beispielsweise Ihrem Fehlerverfolgungsdienst eines Drittanbieters (in diesem Beispiel Rollbar) melden:
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
Binden Sie Puma mit dem Flag -b
(oder --bind
) an einen Socket:
$ puma -b tcp://127.0.0.1:9292
So verwenden Sie einen UNIX-Socket anstelle von TCP:
$ puma -b unix:///var/run/puma.sock
Wenn Sie die Berechtigungen des UNIX-Sockets ändern müssen, fügen Sie einfach einen umask-Parameter hinzu:
$ puma -b 'unix:///var/run/puma.sock?umask=0111'
Brauchen Sie ein bisschen Sicherheit? Verwenden Sie SSL-Sockets:
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert'
localhost
Gem, für Entwicklungszwecke): Puma unterstützt das localhost
Gem für selbstsignierte Zertifikate. Dies ist besonders nützlich, wenn Sie Puma lokal mit SSL verwenden möchten und selbstsignierte Zertifikate für Ihren Anwendungsfall funktionieren. Derzeit ist die Integration nur im MRT einsetzbar.
Puma konfiguriert SSL automatisch, wenn das localhost
Gem in einer development
geladen wird:
Fügen Sie den Edelstein zu Ihrer Gemfile hinzu:
group ( :development ) do
gem 'localhost'
end
Und erfordern Sie es implizit mit dem Bundler:
require "bundler"
Bundler . require ( :default , ENV [ "RACK_ENV" ] . to_sym )
Alternativ können Sie das Gem in Ihrer Konfigurationsdatei anfordern, entweder config/puma/development.rb
, config/puma.rb
, oder es über die CLI-Option -C
festlegen:
require 'localhost'
# configuration methods (from Puma::DSL) as needed
Darüber hinaus muss Puma auf einen SSL-Socket lauschen:
$ 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
Um bestimmte SSL-Verschlüsselungen für TLSv1.2 und niedriger zu verwenden oder zu vermeiden, verwenden Sie die Optionen ssl_cipher_filter
oder 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'
Um die verfügbaren TLSv1.3-Ciphersuites zu konfigurieren, verwenden Sie die Option ssl_ciphersuites
(nicht verfügbar für 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'
Siehe https://www.openssl.org/docs/man1.1.1/man1/ciphers.html für das Verschlüsselungsfilterformat und die vollständige Liste der Verschlüsselungssammlungen.
Deaktivieren Sie TLS v1 mit der Option no_tlsv1
:
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&no_tlsv1=true'
Um die von OpenSSL angebotenen Verifizierungsflags zu aktivieren, verwenden Sie verification_flags
(nicht verfügbar für JRuby):
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&verification_flags=PARTIAL_CHAIN'
Sie können auch mehrere Verifizierungsflags setzen (indem Sie sie durch ein Komma trennen):
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&verification_flags=PARTIAL_CHAIN,CRL_CHECK'
Liste der verfügbaren Flags: 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
(siehe https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_hostflags.html#VERIFICATION-FLAGS).
Um die Laufzeitentschlüsselung eines verschlüsselten SSL-Schlüssels zu aktivieren (nicht verfügbar für JRuby), verwenden Sie 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
muss:
Zum Beispiel:
#! /bin/sh
echo " this is my password "
key_password_command
kann mit key
oder key_pem
verwendet werden. Wenn der Schlüssel nicht verschlüsselt ist, wird die ausführbare Datei nicht aufgerufen.
Puma verfügt über eine integrierte Status- und Steuerungs-App, mit der Puma abgefragt und gesteuert werden kann.
$ puma --control-url tcp://127.0.0.1:9293 --control-token foo
Puma startet den Kontrollserver auf dem Localhost-Port 9293. Alle Anfragen an den Kontrollserver müssen das Kontrolltoken (in diesem Fall token=foo
) als Abfrageparameter enthalten. Dies ermöglicht eine einfache Authentifizierung. Schauen Sie sich Puma::App::Status
oder status.rb an, um zu sehen, was die Status-App zur Verfügung hat.
Sie können auch über pumactl
mit dem Steuerungsserver interagieren. Dieser Befehl startet Puma neu:
$ pumactl --control-url 'tcp://127.0.0.1:9293' --control-token foo restart
Um eine Liste der pumactl
-Optionen anzuzeigen, verwenden Sie pumactl --help
.
Sie können auch eine Konfigurationsdatei mit dem Flag -C
(oder --config
) bereitstellen:
$ puma -C /path/to/config
Wenn keine Konfigurationsdatei angegeben ist, sucht Puma unter config/puma.rb
nach einer Konfigurationsdatei. Wenn eine Umgebung angegeben ist (über das Flag --environment
oder über die Umgebungsvariablen APP_ENV
, RACK_ENV
oder RAILS_ENV
), sucht Puma unter config/puma/<environment_name>.rb
nach einer Konfigurationsdatei und greift dann auf config/puma.rb
zurück .
Wenn Sie verhindern möchten, dass Puma an diesen Speicherorten nach einer Konfigurationsdatei sucht, fügen Sie das Flag --no-config
ein:
$ puma --no-config
# or
$ puma -C "-"
Die anderen Nebeneffekte des Festlegens der Umgebung sind, ob Stapelspuren angezeigt werden sollen (in development
oder test
), und das Festlegen von RACK_ENV kann möglicherweise Auswirkungen auf die Middleware haben, die nach diesem Wert sucht, um ihr Verhalten zu ändern. Der Standardwert für puma RACK_ENV ist development
. Sie können alle Konfigurations-Standardwerte in Puma::Configuration#puma_default_options
oder Configuration.rb sehen.
Schauen Sie sich Puma::DSL
oder dsl.rb an, um alle verfügbaren Optionen zu sehen.
Puma verfügt über die Möglichkeit, sich selbst neu zu starten. Wenn verfügbar (MRT, Rubinius, JRuby), führt Puma einen „Hot Restart“ durch. Dies ist die gleiche Funktionalität wie in Unicorn und NGINX , die die Server-Sockets zwischen Neustarts offen hält. Dadurch wird sichergestellt, dass während des Neustarts keine ausstehenden Anfragen verworfen werden.
Weitere Informationen finden Sie in der Restart-Dokumentation.
Puma reagiert auf mehrere Signale. Eine detaillierte Anleitung zur Verwendung von UNIX-Signalen mit Puma finden Sie in der Signals-Dokumentation.
Einige Plattformen unterstützen nicht alle Puma-Funktionen.
Bei den MRI-Versionen 2.2.7, 2.2.8, 2.2.9, 2.2.10, 2.3.4 und 2.4.1 wird möglicherweise stream closed in another thread (IOError)
. Es kann durch einen Ruby-Fehler verursacht werden. Es kann mit dem Gem https://rubygems.org/gems/stopgap_13632 behoben werden:
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 unterstützt Capistrano mit einem externen Juwel.
Darüber hinaus unterstützt Puma die integrierte Daemonisierung über den Ruby-Gem puma-daemon. Das Gem stellt die daemonize
wieder her, die von Puma ab Version 5 entfernt wurde, jedoch nur für MRI Ruby.
Bei Puma werden üblicherweise Prozessmonitore verwendet. Moderne Prozessmonitore wie systemd oder rc.d sorgen für kontinuierliche Überwachung und Neustarts für erhöhte Zuverlässigkeit in Produktionsumgebungen:
Community-Guides:
Einzelheiten zum Mitwirken finden Sie im Beitragsleitfaden.
Puma unterliegt dem Urheberrecht von Evan Phoenix und seinen Mitwirkenden und ist unter der BSD-3-Klausel-Lizenz lizenziert. Einzelheiten finden Sie in der mitgelieferten LICENSE-Datei.