Блокировка ввода-вывода/Ruby on Rails
Я рассматриваю возможность написания веб-приложения с помощью Rails. Каждый запрос, сделанный пользователем, будет зависеть от вызова внешнего API. Этот внешний API может быть случайным образом очень медленным (2-3 секунды), и поэтому очевидно, что это повлияет на индивидуальный запрос.
В течение этого времени, когда код ожидает возврата внешнего API, будут ли блокироваться дальнейшие пользовательские запросы?
Просто для дальнейшего разъяснения, поскольку, похоже, есть некоторая путаница, это модель, которую я ожидаю:
- Алиса делает запрос к моему веб-приложению. Для этого выполняется вызов API-сервера A. Сервер API A работает медленно и занимает 3 секунды.
- В течение этого времени ожидания, когда приложение Rails вызывает сервер API A, Боб делает запрос, который должен сделать запрос серверу API.
Является ли интерпретатор Ruby (1.9.3) (или что-то в структуре Rails 3.x) блокировать запрос Боба, требуя от него ждать, пока запрос Алисы не будет выполнен?
Ответы
Ответ 1
Если вы используете только один однопоточный, неаудированный сервер (или не используете входы-выходы с событием), да. Среди других решений, использующих Thin и EM-Synchrony, будет избегайте этого.
Разработка, основанная на вашем обновлении:
Нет, ни Ruby, ни Rails не будут блокировать ваше приложение. Вы оставили часть, которая будет, хотя: веб-сервер. Вам также нужно несколько процессов, несколько потоков или связанный с ними сервер в сочетании с выполнением запросов веб-службы с помощью библиотеки событий ввода-вывода.
@alexd описывается с использованием нескольких процессов. Я лично поддерживаю сервер, на который вызывается событие, потому что мне не нужно заранее знать/угадывать, сколько одновременных запросов у меня может быть (или использовать что-то, что вызывает процессы на основе нагрузки). Один процесс nginx
, выходящий из одного thin
процесс может обрабатывать тонны параллельных запросов.
Ответ 2
Ответ на ваш вопрос зависит от сервера, на котором запущено приложение Rails. Что вы сейчас используете? Тонкий? Unicorn? Apache + Passenger?
Я всем сердцем рекомендую Unicorn для вашей ситуации - это позволяет легко запускать несколько серверных процессов параллельно, и вы можете настроить количество параллельных процессов просто путем изменения числа в файле конфигурации. В то время как один рабочий Unicorn обрабатывает запрос с высокой задержкой Алисы, другой рабочий Unicorn может использовать ваши свободные циклы процессора для обработки запроса Боба.
Ответ 3
Скорее всего, да. Очевидно, есть способы обойти это, но ни один из них не является легким.
Лучший вопрос: зачем вам нужно удалять внешний API по каждому запросу? Почему бы не реализовать уровень кэша между вашим Rails-приложением и внешним API и использовать его для большинства запросов?
Таким образом, с некоторой пользовательской логикой для истечения срока действия кэша у вас будет быстрое приложение Rails и все еще сможет использовать внешнюю службу API.