Назад | Перейти на главную страницу

Почему Puma не использует все свои нити?

Я использую puma и nxinx, и, насколько я могу судить, он всегда использует только один поток, даже когда я запускаю его со значением по умолчанию 16 или более потоков. Я установил новое приложение rails, а затем выполнил настройку, описанную здесь:

http://blog.wiemann.name/rails-server

Что дает этот образец конфигурации nginx:

upstream benchmarkapp.com {server unix:/tmp/benchmark_app.sock fail_timeout=0;}
server {
 server_name benchmarkapp.com;
 root /home/tristan/benchmark_app/public;
 try_files $uri/index.html $uri @benchmarkapp.com;
 location @benchmarkapp.com {
 proxy_redirect off;
 proxy_pass http://benchmarkapp.com;
 }
}

Затем создал простое действие контроллера, которое просто засыпает на 3 секунды, а затем отображает «привет»:

class WelcomeController < ApplicationController
  def index
    sleep(2)
    render :text => "hello"   
  end
end

Затем я начал puma с: puma -t 16 -b unix:///tmp/benchmark_app.sock -S /tmp/benchmark_app.state

после запуска я поразил его с 10 одновременными пользователями, используя осаду, и вот результат

 % siege -c 10 -t 60s http://benchmarkapp.com
** SIEGE 2.70
** Preparing 10 concurrent users for battle.
The server is now under siege...
HTTP/1.1 200   2.04 secs:      25 bytes ==> /
HTTP/1.1 200   4.05 secs:      25 bytes ==> /
HTTP/1.1 200   6.06 secs:      25 bytes ==> /
HTTP/1.1 200   8.08 secs:      25 bytes ==> /
HTTP/1.1 200  10.09 secs:      25 bytes ==> /

Это именно то, что я ожидал бы увидеть, если бы приложение работало однопоточным. Возьмите первые два запроса. Они прибывают примерно в одно и то же время. Первый занимает две секунды, пока все хорошо. Но от второго, третьего, ... до 10-го все должны ждать дополнительные 2 секунды для каждого запроса перед ним. Фактически, если я перезапускаю puma только с одним потоком, я получаю именно этот результат.

Что я здесь делаю не так? Как я могу заставить сервер использовать все потоки, порождаемые puma? Если все работает правильно, я ожидаю увидеть:

 % siege -c 10 -t 60s http://benchmarkapp.com
** SIEGE 2.70
** Preparing 10 concurrent users for battle.
The server is now under siege...
HTTP/1.1 200   2.04 secs:      25 bytes ==> /
HTTP/1.1 200   2.05 secs:      25 bytes ==> /
HTTP/1.1 200   2.03 secs:      25 bytes ==> /
HTTP/1.1 200   2.01 secs:      25 bytes ==> /
HTTP/1.1 200   2.06 secs:      25 bytes ==> /

Как я могу это сделать?

Проведя много исследований в Интернете и пытаясь понять, как заставить Puma использовать потоки, я наконец понял.

Ты можешь использовать config.allow_concurrency = true в конфигурации вашего приложения. Это устранит использование Rack::Lock промежуточное программное обеспечение, которое отвечает за безопасность потоков в ruby ​​с использованием GIL (оно гарантирует, что одновременно выполняется только 1 поток).

Чтобы проверить свою конфигурацию, используйте rake middleware и убедитесь, что вы НЕ видите use Rack::Lock в списке.