Я пытаюсь полностью понять варианты параллельной обработки запросов в Rack. Я использовал async_sinatra для создания приложения с длительным опросом, и теперь я экспериментирую с пустой стойкой, используя флаг throw :async
и/или Thin --threaded. Мне нравится эта тема, но есть некоторые вещи, которые я просто не могу понять. (Нет, я не путаю параллелизм с параллелизмом, и да, я понимаю ограничения, налагаемые GIL).
Q1. Мои тесты показывают, что thin --threaded
(т.е. rack.multithread=true
) выполняет запросы одновременно в отдельных потоках (я предполагаю, что использую EM), что означает, что длительный запрос A не будет блокировать запрос B (за исключением ввода-вывода). Это означает, что моему приложению не требуется никакого специального кода (например, обратных вызовов) для достижения параллелизма (опять же, игнорируя блокирующие вызовы БД, ввод-вывод и т. д.). Это то, что, по-моему, я наблюдал. Верно ли это?
Q2. Есть еще один, более часто обсуждаемый способ достижения параллелизма, включающий EventMachine.defer
и throw :async
. Строго говоря, запросы не обрабатываются с помощью потоков. Они обрабатываются последовательно, но их тяжелая работа и обратный вызов передаются EventMachine, который использует async.callback для отправки ответа в более позднее время. После того, как запрос A перенес свою работу в EM.defer, запускается запрос B. Это правильно?
Q3. Предполагая, что вышеизложенное более или менее правильно, имеет ли какое-либо конкретное преимущество одного метода над другим? Очевидно, что --threaded
выглядит как чудодейственное средство. Есть ли недостатки? Если нет, то почему все говорят о async_sinatra
/throw :async
/async.callback
? Возможно, первое — это «я хочу, чтобы мое приложение Rails работало быстрее при большой нагрузке», а второе лучше подходит для приложений с большим количеством длительных запросов? Или, возможно, масштаб является фактором? Тут только предположить.
Я использую Thin 1.2.11 на MRI Ruby 1.9.2. (К вашему сведению, я должен использовать флаг --no-epoll
, так как есть давняя, якобы решенная, но не совсем проблема с использованием EventMachine epoll и Ruby 1.9.2. Это не относится к делу, но приветствуется любое понимание.)