Я использую 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
в списке.