Выполнение большого количества асинхронных операций ввода-вывода в Rails - PullRequest
2 голосов
/ 25 января 2010

Я работаю над приложением Rails, которое периодически должно выполнять большое количество операций ввода-вывода. Эти операции могут выполняться асинхронно. Например, один раз в день для каждого пользователя система должна запросить Salesforce.com, чтобы получить текущий список учетных записей (компаний), которые он отслеживает. Это приводит к огромному количеству (потенциально> 100 тыс.) Небольших запросов.

Наш текущий подход заключается в использовании ActiveMQ с ActiveMessaging. Каждый из наших пользователей помещается в очередь как отдельное сообщение. Затем потребитель вытаскивает пользователя из очереди, запрашивает Salesforce.com и обрабатывает результаты. Но такой подход дает нам ужасную производительность. В рамках одного процесса опроса мы можем обрабатывать только одного пользователя за раз. Таким образом, запросы Salesforce.com становятся сериализованными. Если мы не запустим буквально сотни процессов опроса, мы не сможем приблизиться к насыщению сервера, на котором выполняется опрашивание.

Мы рассматриваем EventMachine как альтернативу. Он имеет преимущество в том, что позволяет запускать большое количество запросов Salesforce.com одновременно в рамках одного процесса EventMachine. Таким образом, мы получаем большой параллелизм и использование нашего сервера.

Но есть две проблемы с EventMachine. 1) Мы теряем надежную доставку сообщений, которую мы имели с ActiveMQ / ActiveMessaging. 2) Мы не можем легко перезапускать нашу EventMachine периодически, чтобы уменьшить влияние роста памяти. Например, с ActiveMessaging у нас есть задание cron, которое перезапускает опросник один раз в день, и это можно сделать, не беспокоясь о потере каких-либо сообщений. Но с EventMachine, если мы перезапустим процесс, мы можем буквально потерять сотни сообщений, которые были в процессе. Единственный способ убедиться в этом - это создать постоянный / надежный уровень доставки поверх EventMachine.

У кого-нибудь есть лучший подход? Каков наилучший способ надежного выполнения большого числа асинхронных операций ввода-вывода?

Ответы [ 4 ]

2 голосов
/ 25 января 2010

Я использовал AMQP с RabbitMQ таким образом, чтобы он работал для вас. Поскольку ActiveMQ реализует AMQP, я думаю, вы можете использовать его аналогичным образом. Я не использовал ActiveMessaging, который хотя и выглядит как потрясающий пакет, но я подозреваю, что он может не подходить для этого варианта использования.

Вот как вы можете это сделать, используя AMQP:

  • Сделайте так, чтобы процесс Rails отправил сообщение, в котором говорилось: "получить информацию для пользователя i".
  • Потребитель извлекает это из очереди сообщений, , убедившись, что указано, что сообщение требует, чтобы 'ack' был окончательно удален из очереди . Это означает, что если сообщение не подтверждено как обработанное, оно в конечном итоге возвращается в очередь для другого работника.
  • Затем рабочий раскручивает сообщение в тысячи маленьких запросов к SalesForce.
  • Когда все эти запросы успешно возвращены, должен быть запущен другой обратный вызов для подтверждения исходного сообщения и возврата «сводного сообщения», в котором вся информация относится к исходному запросу. Ключ использует очередь сообщений, которая позволяет вам подтвердить успешную обработку данного сообщения, и делает это только тогда, когда соответствующая обработка завершена.
  • Другой работник вытаскивает это сообщение из очереди и выполняет любую синхронную работу. Поскольку все биты, вызывающие задержку, уже выполнены, я думаю, что все должно быть в порядке.

Если вы используете (C) Ruby, старайтесь никогда не объединять синхронные и асинхронные компоненты в одном процессе. Процесс должен либо делать все через Eventmachine, без блокировки кода, либо общаться только с процессом Eventmachine через очередь сообщений.

Кроме того, написание асинхронного кода невероятно полезно, но также сложно писать, сложно тестировать и подвержено ошибкам. Быть осторожен. При необходимости изучите другой язык или инструмент.

2 голосов
/ 25 января 2010

Я поддерживаю ActiveMessaging и также думаю о проблемах многопоточного поллера, хотя, возможно, не в таком масштабе, как вы, ребята. Я поделюсь с вами своими мыслями здесь, но также буду рад обсудить дальнейший список активных сообщений или по электронной почте, если хотите.

Одна хитрость в том, что опросер не единственная сериализованная часть этого. Подписки на STOMP, если вы выполняете client -> ack во избежание потери сообщений при прерывании, будут отправлять новое сообщение по данному соединению только тогда, когда предыдущее сообщение было подтверждено. Как правило, вы можете обрабатывать только одно сообщение за одно соединение.

Таким образом, чтобы продолжать использовать брокера, уловка заключается в том, чтобы одновременно открывать много подключений / подписок брокера. Текущий опросчик довольно тяжел для этого, так как он загружает целую среду rails для каждого обработчика, и один опросчик - это одно соединение. Но в текущем устройстве опроса нет ничего магического, я мог бы представить, что приложение опроса является клиентом машины событий, который реализован для создания новых соединений с брокером и получения множества сообщений одновременно.

В своих собственных экспериментах в последнее время я думал об использовании Ruby Enterprise Edition и наличии главного потока, который разветвляет многие рабочие потоки-опрошенные, чтобы получить выгоду от уменьшения занимаемой памяти (так же, как это делает пассажир), но думаю трюк с ЭМ мог бы сработать.

Я также являюсь поклонником проекта Resque, хотя я не знаю, что было бы лучше масштабировать для многих рабочих - я думаю, что рабочие могли бы быть легче.

http://github.com/defunkt/resque

1 голос
/ 26 января 2010

также оформить «корч» и «бобовый стебель»

0 голосов
/ 27 января 2010

Кто-то прислал мне следующую ссылку: http://github.com/mperham/evented/tree/master/qanat/. Это система, которая чем-то похожа на ActiveMessaging, за исключением того, что она построена поверх EventMachine. Это почти то, что нам нужно. Единственная проблема заключается в том, что он работает только с очередью Amazon, а не с ActiveMQ.

...