Puma es un servidor HTTP 1.1 simple, rápido, multiproceso y altamente paralelo para aplicaciones Ruby/Rack .
Puma es un servidor para aplicaciones HTTP alimentadas por Rack escritas en Ruby. Es:
Originalmente diseñado como servidor para Rubinius, Puma también funciona bien con Ruby (MRI) y JRuby.
En MRI, hay un bloqueo global de VM (GVL) que garantiza que solo un subproceso pueda ejecutar código Ruby a la vez. Pero si está bloqueando mucho IO (como llamadas HTTP a API externas como Twitter), Puma aún mejora el rendimiento de MRI al permitir que la espera de IO se realice en paralelo. Las implementaciones de Ruby verdaderamente paralelas (TruffleRuby, JRuby) no tienen esta limitación.
$ gem install puma
$ puma
Sin argumentos, puma buscará un archivo rackup (.ru) en el directorio de trabajo llamado config.ru
.
Puma instalará/compilará con soporte para sockets SSL, suponiendo que los archivos de desarrollo OpenSSL estén instalados en el sistema.
Si el sistema no tiene instalados los archivos de desarrollo OpenSSL, Puma instalará/compilará, pero no permitirá conexiones SSL.
Puma es el servidor predeterminado para Rails, incluido en el Gemfile generado.
Inicie su servidor con el comando rails
:
$ rails server
Muchas opciones de configuración y funciones de Puma no están disponibles cuando se utiliza rails server
. Se recomienda utilizar el ejecutable de Puma en su lugar:
$ bundle exec puma
Puedes ejecutar tu aplicación Sinatra con Puma desde la línea de comando de esta manera:
$ ruby app.rb -s Puma
Sin embargo, para configurar Puma usando un archivo de configuración, como puma.rb
, debe usar el ejecutable puma
. Para hacer esto, debes agregar un archivo rackup a tu aplicación Sinatra:
# config.ru
require './app'
run Sinatra :: Application
Luego puede iniciar su aplicación usando:
$ bundle exec puma
Puma ofrece numerosas opciones. Consulte puma -h
(o puma --help
) para obtener una lista completa de las opciones CLI, o consulte Puma::DSL
o dsl.rb.
También puede encontrar varios ejemplos de configuración como parte del conjunto de pruebas.
Para fines de depuración, puede configurar la variable de entorno PUMA_LOG_CONFIG
con un valor y la configuración cargada se imprimirá como parte del proceso de arranque.
Puma utiliza un grupo de subprocesos. Puede establecer el número mínimo y máximo de subprocesos que están disponibles en el grupo con el indicador -t
(o --threads
):
$ puma -t 8:32
Puma escalará automáticamente la cantidad de subprocesos, desde el mínimo hasta el máximo, en función de la cantidad de tráfico presente. El valor predeterminado actual es 0:16
y en la resonancia magnética es 0:5
. Siéntase libre de experimentar, pero tenga cuidado de no establecer el número máximo de subprocesos en un número grande, ya que puede agotar los recursos del sistema (o causar contención por el bloqueo global de VM, cuando se usa MRI).
Tenga en cuenta que, además, Puma crea subprocesos por sí solo para fines internos (por ejemplo, para manejar clientes lentos). Entonces, incluso si especifica -t 1:1, espere que se creen alrededor de 7 subprocesos en su aplicación.
Puma también ofrece "modo agrupado". El modo agrupado fork
a los trabajadores de un proceso maestro. Cada proceso hijo todavía tiene su propio grupo de subprocesos. Puede ajustar la cantidad de trabajadores con el indicador -w
(o --workers
):
$ puma -t 8:32 -w 3
O con la variable de entorno WEB_CONCURRENCY
:
$ WEB_CONCURRENCY=3 puma -t 8:32
Tenga en cuenta que los subprocesos todavía se utilizan en modo agrupado y la configuración del indicador -t
subproceso es por trabajador, por lo que -w 2 -t 16:16
generará 32 subprocesos en total, con 16 en cada proceso de trabajo.
Si la variable de entorno WEB_CONCURRENCY
está configurada en "auto"
y la gema concurrent-ruby
está disponible en su aplicación, Puma establecerá el recuento de procesos de trabajo según el resultado de los procesadores disponibles.
Para obtener una discusión en profundidad sobre las ventajas y desventajas de la configuración del recuento de procesos y subprocesos, consulte nuestros documentos.
En modo agrupado, Puma puede "precargar" su aplicación. Esto carga todo el código de la aplicación antes de la bifurcación. La precarga reduce el uso total de memoria de su aplicación a través de una función del sistema operativo llamada copia en escritura.
Si la variable de entorno WEB_CONCURRENCY
se establece en un valor > 1 (y no se ha especificado --prune-bundler
), la precarga se habilitará de forma predeterminada. De lo contrario, puede utilizar el indicador --preload
desde la línea de comando:
$ puma -w 3 --preload
O, si está utilizando un archivo de configuración, puede utilizar preload_app!
método:
# config/puma.rb
workers 3
preload_app!
La precarga no se puede utilizar con el reinicio por fases, ya que el reinicio por fases mata y reinicia a los trabajadores uno por uno, y la precarga copia el código maestro en los trabajadores.
Cuando se utiliza el modo agrupado, el DSL de configuración de Puma proporciona ganchos before_fork
y on_worker_boot
para ejecutar código cuando el proceso maestro se bifurca y los trabajadores secundarios se inician respectivamente.
¡Se recomienda utilizar estos ganchos con preload_app!
, de lo contrario, las constantes cargadas por su aplicación (como Rails
) no estarán disponibles dentro de los ganchos.
# 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
Además, hay un gancho on_refork
que se usa solo en el modo fork_worker
, cuando el proceso hijo del trabajador 0 bifurca a un trabajador nieto:
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
Es importante tener en cuenta las siguientes consideraciones cuando Ruby bifurca un proceso hijo:
SocketError
, Errno::EPIPE
y EOFError
.Por lo tanto, recomendamos lo siguiente:
before_fork
y on_refork
para desconectar las conexiones del socket principal al bifurcar, de modo que no se copien accidentalmente en el proceso secundario.on_worker_boot
para reiniciar cualquier hilo en segundo plano en el hijo bifurcado. El DSL de configuración de Puma proporciona enlaces de ciclo de vida del proceso maestro on_booted
, on_restart
y on_stopped
que pueden usarse para especificar bloques de código que se ejecutarán en cada evento:
# 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
Si Puma encuentra un error fuera del contexto de su aplicación, responderá con un 400/500 y un mensaje de error de texto simple (consulte Puma::Server#lowlevel_error
o server.rb). Puede especificar un comportamiento personalizado para este escenario. Por ejemplo, puede informar el error a su servicio de seguimiento de errores de terceros (en este ejemplo, 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
Vincula Puma a un socket con el indicador -b
(o --bind
):
$ puma -b tcp://127.0.0.1:9292
Para utilizar un socket UNIX en lugar de TCP:
$ puma -b unix:///var/run/puma.sock
Si necesita cambiar los permisos del socket UNIX, simplemente agregue un parámetro umask:
$ puma -b 'unix:///var/run/puma.sock?umask=0111'
¿Necesitas un poco de seguridad? Utilice sockets SSL:
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert'
localhost
, para uso de desarrollo): Puma admite la gema localhost
para certificados autofirmados. Esto es particularmente útil si desea utilizar Puma con SSL localmente y los certificados autofirmados funcionarán para su caso de uso. Actualmente, la integración sólo se puede utilizar en resonancia magnética.
Puma configura automáticamente SSL cuando la gema localhost
se carga en un entorno development
:
Agrega la gema a tu Gemfile:
group ( :development ) do
gem 'localhost'
end
Y requerirlo implícitamente usando el paquete:
require "bundler"
Bundler . require ( :default , ENV [ "RACK_ENV" ] . to_sym )
Alternativamente, puede solicitar la gema en su archivo de configuración, ya sea config/puma/development.rb
, config/puma.rb
, o configurarla mediante la opción -C
cli:
require 'localhost'
# configuration methods (from Puma::DSL) as needed
Además, Puma debe estar escuchando un socket 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
Para usar o evitar cifrados SSL específicos para TLSv1.2 y versiones anteriores, use las opciones ssl_cipher_filter
o 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'
Para configurar los conjuntos de cifrado TLSv1.3 disponibles, utilice la opción ssl_ciphersuites
(no disponible para 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'
Consulte https://www.openssl.org/docs/man1.1.1/man1/ciphers.html para conocer el formato del filtro de cifrado y la lista completa de conjuntos de cifrado.
Deshabilite TLS v1 con la opción no_tlsv1
:
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&no_tlsv1=true'
Para habilitar los indicadores de verificación ofrecidos por OpenSSL, use verification_flags
(no disponible para JRuby):
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&verification_flags=PARTIAL_CHAIN'
También puedes configurar varios indicadores de verificación (separándolos con una coma):
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&verification_flags=PARTIAL_CHAIN,CRL_CHECK'
Lista de indicadores disponibles: 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
(ver https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_hostflags.html#VERIFICATION-FLAGS).
Para habilitar el descifrado en tiempo de ejecución de una clave SSL cifrada (no disponible para JRuby), utilice 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
debe:
Por ejemplo:
#! /bin/sh
echo " this is my password "
key_password_command
se puede utilizar con key
o key_pem
. Si la clave no está cifrada, no se llamará al ejecutable.
Puma tiene una aplicación de control y estado incorporada que se puede utilizar para consultar y controlar Puma.
$ puma --control-url tcp://127.0.0.1:9293 --control-token foo
Puma iniciará el servidor de control en el puerto localhost 9293. Todas las solicitudes al servidor de control deberán incluir el token de control (en este caso, token=foo
) como parámetro de consulta. Esto permite una autenticación sencilla. Consulte Puma::App::Status
o status.rb para ver qué tiene disponible la aplicación de estado.
También puedes interactuar con el servidor de control a través de pumactl
. Este comando reiniciará Puma:
$ pumactl --control-url 'tcp://127.0.0.1:9293' --control-token foo restart
Para ver una lista de opciones pumactl
, use pumactl --help
.
También puede proporcionar un archivo de configuración con el indicador -C
(o --config
):
$ puma -C /path/to/config
Si no se especifica ningún archivo de configuración, Puma buscará un archivo de configuración en config/puma.rb
. Si se especifica un entorno (a través del indicador --environment
o mediante las variables de entorno APP_ENV
, RACK_ENV
o RAILS_ENV
) Puma busca un archivo de configuración en config/puma/<environment_name>.rb
y luego recurre a config/puma.rb
.
Si desea evitar que Puma busque un archivo de configuración en esas ubicaciones, incluya el indicador --no-config
:
$ puma --no-config
# or
$ puma -C "-"
Los otros efectos secundarios de configurar el entorno son si se muestran seguimientos de la pila (en development
o test
), y configurar RACK_ENV puede afectar potencialmente al middleware que busca este valor para cambiar su comportamiento. El valor predeterminado de Puma RACK_ENV es development
. Puede ver todos los valores predeterminados de configuración en Puma::Configuration#puma_default_options
o Configuration.rb.
Consulte Puma::DSL
o dsl.rb para ver todas las opciones disponibles.
Puma incluye la capacidad de reiniciarse. Cuando está disponible (MRI, Rubinius, JRuby), Puma realiza un "reinicio en caliente". Esta es la misma funcionalidad disponible en Unicorn y NGINX que mantiene abiertos los sockets del servidor entre reinicios. Esto garantiza que no se eliminen solicitudes pendientes mientras se realiza el reinicio.
Para obtener más información, consulte la documentación sobre reinicio.
Puma responde a varias señales. Puede encontrar una guía detallada sobre el uso de señales UNIX con Puma en la documentación de Señales.
Algunas plataformas no son compatibles con todas las funciones de Puma.
Para las versiones de MRI 2.2.7, 2.2.8, 2.2.9, 2.2.10, 2.3.4 y 2.4.1, es posible que vea stream closed in another thread (IOError)
. Puede deberse a un error de Ruby. Se puede arreglar con la gema 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 tiene apoyo para Capistrano con una joya externa.
Además, Puma tiene soporte para demonización incorporada a través de la gema puma-daemon ruby. La gema restaura la opción daemonize
que se eliminó de Puma a partir de la versión 5, pero solo para MRI Ruby.
Es común utilizar monitores de procesos con Puma. Los monitores de procesos modernos como systemd o rc.d brindan monitoreo y reinicios continuos para una mayor confiabilidad en entornos de producción:
Guías comunitarias:
Encuentre detalles para contribuir en la guía de contribuciones.
Puma tiene derechos de autor de Evan Phoenix y colaboradores, bajo la licencia BSD de 3 cláusulas. Consulte el archivo de LICENCIA incluido para obtener más detalles.