Примечание: я использую Thin как синоним для всех веб-серверов, реализующих расширение async Rack (т.е. Rainbows !, Ebb, будущие версии Puma, ...)
Q1. Правильно. Он обернет генерацию ответа (aka call
) в EventMachine.defer { ... }
, что приведет к тому, что EventMachine поместит его в свой встроенный пул потоков.
Q2. Использование async.callback
в сочетании с EM.defer
на самом деле не имеет особого смысла, так как в нем также будет использоваться пул потоков, в результате чего получится аналогичная конструкция, как описано в Q1. , Использование async.callback
имеет смысл при использовании только библиотек событий для ввода-вывода. Thin отправит ответ клиенту после вызова env['async.callback']
с обычным ответом Rack в качестве аргумента.
Если тело является EM::Deferrable
, Тонкий не закроет соединение, пока этот отсрочка не преуспеет. Довольно хорошо сохранившийся секрет: если вы хотите больше, чем просто длительный опрос (т.е. оставить соединение открытым после отправки частичного ответа), вы также можете вернуть EM::Deferrable
в качестве объекта body напрямую, без использования throw :async
или кода состояния -1
.
Q3. Вы догадались правильно. Подача с резьбой может улучшить нагрузку на остальное без изменений приложение Rack. Я вижу улучшение на 20% для простых приложений Sinatra на моей машине с Ruby 1.9.3, даже больше при работе на Rubinius или JRuby, где могут использоваться все ядра. Второй подход полезен, если вы пишете свое заявление равномерно.
Вы можете бросить много магии и взломов поверх Rack, чтобы приложение, не выравненное по частоте, использовало эти механизмы (см. Em-synchrony или sinatra-synchrony), но это оставит вас в аду отладки и зависимости.
Асинхронный подход имеет смысл с приложениями, которые, как правило, лучше всего решаются с помощью четного подхода, например веб-чат . Однако я бы не рекомендовал использовать многопоточный подход для реализации длинного опроса, потому что каждое соединение опроса блокирует поток. Это оставит вас с кучей потоков или соединений, с которыми вы не можете справиться. Пул потоков EM по умолчанию имеет размер 20 потоков, что ограничивает до 20 ожидающих подключений на процесс.
Вы можете использовать сервер, который создает новый поток для каждого входящего соединения, но создание потоков стоит дорого (за исключением MacRuby, но я бы не использовал MacRuby в любом рабочем приложении). Примерами являются serv и net-http-server . В идеале, вы хотите, чтобы n: m отображало запросы и потоки. Но не существует сервера, предлагающего это.
Если вы хотите узнать больше по этой теме: я выступил с докладом об этом на Rocky Mountain Ruby (и на множестве других конференций). Видеозапись можно найти на конфроках .