Асинхронное повторение ответа на запрос с помощью Thin и Sinatra
Если ваш ответ в Sinatra возвращает объект "eachable", цикл событий Sinatra будет "каждый" ваш результат и выдаст результаты потоковым способом в виде HTTP-ответа. Однако, если есть параллельные запросы к Sinatra, он будет перебирать все элементы одного ответа, прежде чем обрабатывать другой запрос. Если у нас есть курсор на результаты некоторого запроса БД, это означает, что мы должны ждать, пока все данные будут доступны, прежде чем обрабатывать параллельный запрос.
Я посмотрел в асинхронном-Синатра джем и http://macournoyer.com/blog/2009/06/04/pusher-and-async-with-thin/, думая, что это решит мою проблему, но я попробовал этот пример:
require 'sinatra/async'
class AsyncTest < Sinatra::Base
register Sinatra::Async
aget '/' do
body "hello async"
end
aget '/delay/:n' do |n|
EM.add_timer(n.to_i) { body { "delayed for #{n} seconds" } }
end
end
И /delay/5
запрос не работает одновременно, как я ожидаю, то есть я делаю 3 запроса одновременно, и отладчик Chrome отмечает время отклика примерно 5, 10 и 15 секунд.
Я пропустил какую-то настройку или есть другой способ сказать Sinatra / Thin обрабатывать запросы одновременно образом?
Обновление: вот еще один ключ в этом (или, возможно, проясняет вещи):
Запуск curl -i http://localhost:3000/delay/5
одновременно имеет правильное поведение (2 запроса каждый возвращаются через ~5 секунд). Запуск ab -c 10 -n 50 http://locahost:3000/delay/5
(утилита Apache benchmark) также возвращает что-то разумное за общее время (~25 секунд). Firefox демонстрирует то же поведение, что и Chrome. Чем браузеры отличаются от утилит командной строки?
2 ответа:
Таким образом, в конце концов, я обнаружил, что пример действительно работает, и я мог бы в конечном итоге заставить Синатру передавать каждый из возможных результатов одновременно, в основном используя идею
EM.defer
в Pusher и Async page. Curl и Apache benchmarking подтвердили, что это работает.Причина, по которой он не работал в браузере, заключается в том, что браузеры ограничивают количество подключений к одному и тому же URL. Я знал, что существует ограничение на одновременные подключения к одному домену (также низкое число), но не что (по-видимому) все соединения с одним URI сериализованы:
Http://maillist.caucho.com/pipermail/resin-interest/2009-August/003998.html
Я не знаю, можно ли это настроить, я вижу только доменную конфигурацию в Firefox, но это было проблемой.
Когда вы собираетесь обработать ответ объекта, сделайте следующее:
fork do handle request... exit 99 end
И если вам не нужно, не ждите окончания этого дочернего процесса.. с a:
child = fork do handle request... exit 99 end Process.detach(child)
Это простой способ обработки нескольких запросов, однако я не уверен, что ORM вы можете использовать для этих запросов БД, но вы можете попасть в проблемы блокировки уровня таблицы/строки с несколькими процессами, пытающимися попасть в БД, если это то, что вы имеете в виду, когда говорите об обработке запросов...