Puma — это простой, быстрый, многопоточный и высоко параллельный HTTP 1.1 сервер для приложений на Ruby/Rack.
Puma — это сервер для Rack-powered HTTP приложений, написанных на Ruby. Он:
На MRI существует глобальный блокировщик виртуальной машины (GVL), который гарантирует, что только один поток может выполнять Ruby-код одновременно. Но если вы выполняете много блокирующего ввода-вывода (например, HTTP-вызовы к внешним API, таким как Twitter), Puma все равно улучшает пропускную способность MRI, позволяя ожиданию ввода-вывода выполняться параллельно. Настоящие параллельные реализации Ruby (TruffleRuby, JRuby) не имеют этой ограничивающей функции.
$ gem install puma
$ puma
Без аргументов, puma будет искать файл rackup (.ru) в рабочей директории с именем config.ru
.
Puma будет установлен/скомпилирован с поддержкой SSL-сокетов, предполагая, что файлы разработки OpenSSL установлены на системе.
Если на системе не установлены файлы разработки OpenSSL, Puma будет установлен/скомпилирован, но он не будет поддерживать SSL-соединения.
Puma — это по умолчанию используемый сервер для Rails, включенный в сгенерированный Gemfile.
Запустите свой сервер с помощью команды rails
:
$ rails server
Многие опции конфигурации и функции Puma недоступны при использовании rails server
. Рекомендуется использовать исполняемый файл Puma:```
$ bundle exec puma
### Sinatra
Вы можете запустить свое приложение на Sinatra с помощью Puma из командной строки следующим образом:
$ ruby app.rb -s Puma
Чтобы на самом деле настроить Puma с помощью конфигурационного файла, такого как `puma.rb`, вам нужно использовать исполняемый файл `puma`. Для этого вам необходимо добавить файл rackup в ваше приложение на Sinatra:
```ruby
# config.ru
require './app'
run Sinatra::Application
Затем вы можете запустить свое приложение с помощью:
$ bundle exec puma
Puma предоставляет множество опций. Чтобы получить полный список опций командной строки, выполните puma -h
(или puma --help
) или посмотрите Puma::DSL
или dsl.rb.
Вы также можете найти несколько примеров конфигурации как часть теста.
Для целей отладки вы можете установить переменную окружения PUMA_LOG_CONFIG
со значением, и загруженная конфигурация будет выводиться как часть процесса загрузки.
Puma использует пул потоков. Вы можете задать минимальное и максимальное количество потоков, доступных в пуле, с помощью флага -t
(или --threads
):
$ puma -t 8:32
```Puma автоматически масштабирует количество потоков от минимального до максимального в зависимости от наличия трафика. Текущие значения по умолчанию — `0:16` и на MRI — `0:5`. Пожалуйста, экспериментируйте, но будьте осторожны при установке большого числа максимальных потоков, так как это может привести к исчерпанию ресурсов системы (или конкуренции за блокировку глобального VM, при использовании MRI).Обратите внимание, что Puma также создает потоки для внутренних целей (например, обработки медленных клиентов). Поэтому, даже если вы зададите `-t 1:1`, ожидайте создания около 7 потоков в вашем приложении.
### Режим кластера
Puma также предлагает "режим кластера". В режиме кластера Puma создает рабочие процессы от основного процесса. Каждый дочерний процесс все еще имеет свой собственный пул потоков. Вы можете настроить количество рабочих процессов с помощью флага `-w` (или `--workers`):
$ puma -t 8:32 -w 3
Или с использованием переменной окружения `WEB_CONCURRENCY`:
$ WEB_CONCURRENCY=3 puma -t 8:32
Обратите внимание, что потоки всё ещё используются в режиме кластера, и настройка флага потока `-t` задаётся для каждого рабочего процесса, поэтому `-w 2 -t 16:16` запустит всего 32 потока, по 16 в каждом рабочем процессе.
Если переменная окружения `WEB_CONCURRENCY` установлена в значение `"auto"` и библиотека `concurrent-ruby` доступна в вашем приложении, Puma установит количество рабочих процессов в результате [доступных процессоров](https://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent.html#available_processor_count-class_method).
Для подробного обсуждения компромиссов настроек количества потоков и процессов, [см. наши документы](https://github.com/puma/puma/blob/9282a8efa5a0c48e39c60d22ca70051a25df9f55/docs/kubernetes.md#workers-per-pod-and-other-config-issues).В режиме кластера Puma может "предзагрузить" ваше приложение. Это загружает весь код приложения *до* форка. Предзагрузка снижает общее использование памяти вашего приложения за счёт функции операционной системы, называемой [copy-on-write](https://en.wikipedia.org/wiki/Copy-on-write).Если переменная окружения `WEB_CONCURRENCY` установлена в значение > 1 (и флаг `--prune-bundler` не указан), предзагрузка будет включена по умолчанию. В противном случае вы можете использовать флаг `--preload` из командной строки:
$ puma -w 3 --preload
Или, если вы используете файл конфигурации, вы можете использовать метод `preload_app!`:
```ruby
# config/puma.rb
workers 3
preload_app!
Предзагрузка не может использоваться с фазированным перезапуском, так как фазированный перезапуск убивает и перезапускает рабочие процессы по одному, а предзагрузка копирует код мастера в рабочие процессы.
При использовании режима кластера конфигурационный DSL Puma предоставляет хуки before_fork
и on_worker_boot
для выполнения кода при форке основного процесса и запуске рабочих процессов соответственно.
Рекомендуется использовать эти хуки с preload_app!
, в противном случае константы, загруженные вашим приложением (например, Rails
), не будут доступны внутри хуков.
# config/puma.rb
before_fork do
# Добавьте код для выполнения внутри основного процесса Puma перед форком рабочего процесса.
end
on_worker_boot do
# Добавьте код для выполнения внутри рабочего процесса Puma после форка.
end
Кроме того, есть on_refork
и after_refork
хуки, которые используются только в режиме fork_worker
, когда рабочий процесс 0 ребёнка форкает внучатого рабочего.```ruby
on_refork do
end
```ruby
after_refork do
# Used only when fork_worker mode is enabled. Add code to be executed inside Puma worker process 0
# child after it forks the grandchild worker.
end
Важно отметить следующие соображения при форке Ruby ребёнка:
SocketError
, Errno::EPIPE
, и EOFError
.Поэтому мы рекомендуем следующее:1. Если это возможно, не устанавливайте никаких сокетных подключений (HTTP, подключения к базе данных и т.д.) внутри основного процесса Puma при загрузке.
2. Если (1) невозможно, используйте before_fork
и on_refork
для отключения сокетных подключений родителя при форке, чтобы они не были случайно скопированы в дочерний процесс.
3. Используйте on_worker_boot
для перезапуска любых фоновых потоков в форкнутом дочернем процессе.
4. Используйте after_refork
для перезапуска любых фоновых потоков в родительском процессе.#### Хуки жизненного цикла основного процесса
Конфигурационный DSL Puma предоставляет хуки жизненного цикла основного процесса on_booted
, on_restart
и on_stopped
,
которые могут быть использованы для указания блоков кода для выполнения при каждом событии:
# config/puma.rb
on_booted do
# Добавьте код для выполнения в основном процессе Puma после его загрузки,
# и также после завершения фазированного перезапуска.
end
on_restart do
# Добавьте код для выполнения в основном процессе Puma при получении
# команды перезапуска, но до перезапуска.
end
on_stopped do
# Добавьте код для выполнения в основном процессе Puma при получении
# команды остановки, но до завершения.
end
Если Puma обнаруживает ошибку вне контекста вашего приложения, он ответит статусом 400/500 и простым текстовым сообщением об ошибке (см. Puma::Server#lowlevel_error
или server.rb).
Вы можете указать пользовательское поведение для этой ситуации. Например, вы можете отправить сообщение об ошибке в вашу службу отслеживания ошибок (в этом примере, Rollbar):```ruby
lowlevel_error_handler do |e, env, status|
if status == 400
message = "Сервер не смог обработать запрос из-за ошибки, такой как неправильно введенный URL, неправильная синтаксическая конструкция или URL, содержащий недопустимые символы.\n"
else
message = "Произошла ошибка, и инженеры были уведомлены. Пожалуйста, перезагрузите страницу. Если у вас возникли проблемы, свяжитесь с support@example.com\n"
Rollbar.critical(e)
end
end
end
Привяжите Puma к сокету с помощью флага -b
(или --bind
):
$ 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'
localhost
, для использования в разработке):Puma поддерживает gem localhost
для самозаверенных сертификатов. Это особенно полезно, если вы хотите использовать Puma с SSL локально, и самозаверенные сертификаты будут работать для вашего случая. В настоящее время интеграция может использоваться только в MRI.
Puma автоматически настраивает SSL, когда gem localhost
загружается в среде development
:
Добавьте gem в ваш Gemfile:
group(:development) do
gem 'localhost'
end
И требуйте его неявно с помощью bundler:
require "bundler"
Bundler.require(:default, ENV["RACK_ENV"].to_sym)
В качестве альтернативы, вы можете требовать gem в вашем файле конфигурации, либо config/puma/development.rb
, либо config/puma.rb
, либо задать через опцию -C
командной строки:
require 'localhost'
# методы конфигурации (из Puma::DSL) по мере необходимости
Кроме того, Puma должен прослушивать SSL сокет:
$ puma -b 'ssl://localhost:9292' -C config/use_local_host.rb
```# Следующие опции позволяют вам получить доступ к Puma через HTTP:
$ puma -b ssl://localhost:9292 -b tcp://localhost:9393 -C config/use_local_host.rb
Чтобы использовать или избегать конкретных шифров SSL для TLSv1.2 и ниже, используйте опции ssl_cipher_filter
или 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'
Чтобы настроить доступные TLSv1.3 наборы шифров, используйте опцию ssl_ciphersuites
(не доступна для 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'
См. https://www.openssl.org/docs/man1.1.1/man1/ciphers.html для формата фильтра шифров и полного списка наборов шифров.
Отключение TLS v1 с помощью опции no_tlsv1
:
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&no_tlsv1=true'
Чтобы включить флаги проверки, предлагаемые OpenSSL, используйте опцию verification_flags
(не доступна для JRuby):
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&verification_flags=PARTIAL_CHAIN'
Вы также можете задать несколько флагов проверки (разделяя их запятыми):
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&verification_flags=PARTIAL_CHAIN,CRL_CHECK'
```Список доступных флагов: `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`
(см. https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_hostflags.html#VERIFICATION-FLAGS).#### Управление расшифровкой пароля OpenSSLДля включения расшифровки в режиме выполнения зашифрованного SSL-ключа (не доступно для JRuby), используйте `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` должен:
1. Быть исполняемым Puma.
2. Выводить пароль расшифровки на stdout.
Пример:
```shell
#!/bin/sh
echo "this is my password"
key_password_command
можно использовать с key
или key_pem
. Если ключ не зашифрован, исполняемый файл не будет запущен.
Puma имеет встроенный статусный и управляющий приложения, которые можно использовать для запроса и управления Puma.
$ puma --control-url tcp://127.0.0.1:9293 --control-token foo
Puma запустит сервер управления на локальном хосте на порту 9293. Все запросы к серверу управления должны включать токен управления (в данном случае, token=foo
) как параметр запроса. Это позволяет для простой аутентификации. Изучите Puma::App::Status
или status.rb, чтобы узнать, какие возможности доступны в статусном приложении.
Вы также можете взаимодействовать с сервером управления через pumactl
. Этот командный файл перезапустит Puma:
$ pumactl --control-url 'tcp://127.0.0.1:9293' --control-token foo restart
Чтобы увидеть список опций pumactl
, используйте pumactl --help
.
Вы также можете предоставить файл конфигурации с помощью флага -C
(или --config
):```
$ puma -C /path/to/config
Если файл конфигурации не указан, Puma будет искать файл конфигурации по пути `config/puma.rb`. Если указано окружение (через флаг `--environment` или через переменные окружения `APP_ENV`, `RACK_ENV`, или `RAILS_ENV`), Puma будет искать файл конфигурации по пути `config/puma/<environment_name>.rb` и затем будет пытаться использовать `config/puma.rb`.
Если вы хотите предотвратить Puma от поиска файла конфигурации в этих местах, включите флаг `--no-config`:
$ puma --no-config
$ puma -C "-"
Другие побочные эффекты установки окружения включают отображение трассировок стека (в `development` или `test`), и установка RACK_ENV может повлиять на промежуточные слои, которые ищут это значение для изменения своего поведения. Значение RACK_ENV по умолчанию для Puma — `development`. Вы можете увидеть все значения по умолчанию конфигурации в `Puma::Configuration#puma_default_options` или [configuration.rb](https://github.com/puma/puma/blob/61c6213fbab/lib/puma/configuration.rb#L182-L204). Просмотрите `Puma::DSL` или [dsl.rb](https://github.com/puma/puma/blob/master/lib/puma/dsl.rb), чтобы узнать о всех доступных опциях.
## Перезапуск
Puma включает возможность перезапуска себя. Когда это возможно (MRI, Rubinius, JRuby), Puma выполняет "горячий перезапуск". Это та же функциональность, доступная в *Unicorn* и *NGINX*, которые сохраняют серверные сокеты открытыми между перезапусками. Это гарантирует, что нет отброшенных ожидающих запросов во время перезапуска.Для получения дополнительной информации см. документацию по [перезапуску](docs/restart.md).
## Сигналы
Puma отвечает на несколько сигналов. Подробное руководство по использованию UNIX сигналов с Puma можно найти в документации по [сигналам](docs/signals.md).
## Ограничения платформ
Некоторые платформы не поддерживают все функции Puma.
* **JRuby**, **Windows**: серверные сокеты не являются бесшовными при перезапуске, они должны быть закрыты и заново открыты. Эти платформы не имеют способа передачи дескрипторов в новый процесс, доступный Ruby. Также режим кластера не поддерживается из-за отсутствия fork(2).
* **Windows**: режим кластера не поддерживается из-за отсутствия fork(2).
* **Kubernetes**: Способ, которым Kubernetes управляет завершением работы падов, плохо взаимодействует с серверными процессами, реализующими грациозное завершение работы, такими как Puma. Подробнее см. раздел [Kubernetes](docs/kubernetes.md) документации.
## Знаменитые ошибки
Для версий MRI 2.2.7, 2.2.8, 2.2.9, 2.2.10, 2.3.4 и 2.4.1 вы можете увидеть ```поток закрыт в другой поток (IOError)```. Это может быть вызвано [ошибкой Ruby](https://bugs.ruby-lang.org/issues/13632). Это можно исправить с помощью гема https://rubygems.org/gems/stopgap_13632:
```ruby
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
daemonize
, которая была удалена из Puma начиная с версии 5, но только для MRI Ruby.Использование процессных мониторов с Puma является распространённой практикой. Современные процессные мониторы, такие как systemd или rc.d, предоставляют непрерывное мониторинг и перезапуски для повышения надёжности в производственной среде:
Командные руководства:
puma-metrics — экспортирует метрики Puma в Prometheus
puma-plugin-statsd — отправляет метрики Puma в statsd
puma-plugin-systemd — более глубокая интеграция с systemd для уведомлений, статуса и вордога. В Puma 5.1.0 была интегрирована поддержка уведомлений и вордога, что, вероятно, конфликтует с этим плагином. В Puma 6.1.0 была добавлена поддержка статуса, что полностью устаревает этот плагин.
puma-plugin-telemetry — плагин для сбора телеметрии Puma, предлагающий различные цели для публикации
puma-acme — автоматическое развертывание и настройка сертификатов SSL/HTTPS### Мониторинг
puma-status — мониторинг CPU/Mem/Load запущенных экземпляров Puma из командной строки
Подробности о вкладе содержатся в руководстве по вкладу.
Puma защищена авторским правом Evan Phoenix и вкладчиков, лицензирована под лицензией BSD 3-Клause. Подробности содержатся в включённом файле LICENSE.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )