Heroku - проблема из-за нескольких динамовцев - PullRequest
0 голосов
/ 08 марта 2011

В моем приложении rails я использую API синтаксического анализа SendGrid, который отправляет почту на мой сервер. Время от времени API синтаксического анализа SendGrid отправляет одно и то же сообщение электронной почты дважды.

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

Теперь я перенес этот концерт в heroku, где у меня есть 2+ динамометра, и это не сработало. Я предполагаю, что это как-то связано с репликацией. В таком случае, как масштабируемые сайты с несколькими серверами могут иметь дело с чем-то вроде этого?

Спасибо

Ответы [ 2 ]

2 голосов
/ 08 марта 2011

Вы должны посмотреть на использование фоновой очереди заданий. У Героку есть « Рабочие » (что было отложенной работой). Вместо немедленной отправки электронного письма вы помещаете его в очередь. Затем к вашей учетной записи необходимо добавить одного или нескольких «рабочих» Heroku, и каждый из них будет последовательно выполнять задания. Это означает, что перед отправкой электронной почты может быть небольшая задержка (в зависимости от нагрузки), но эта задержка не представляется пользователю, и если вам нужно отправить много писем, просто добавьте больше работников.

Ожидание внешней службы, такой как поставщик электронной почты, при каждом пользовательском действии опасно, поскольку любая сетевая проблема приведет к сбою вашего сайта, поскольку нескольким пользователям придется «ждать», когда на их HTTP-запросы будут даны ответы, пока Heroku блокируется этими третьими. групповые звонки.

В этой ситуации с работниками каждая работа потерпела бы неудачу, но была бы повторена и в конечном итоге преуспела.

0 голосов
/ 21 марта 2013

Похоже, это может быть проблема транзакции.Если у вас одновременно работают несколько рабочих, их работа может быть чередованной.Например, эта последовательность событий приведет к отправке 2 писем.

Работник A: проверяет существующую запись и не находит одного работника B: проверяет существующую запись и не находит одного работника A: Опубликовать в Sendgrid Worker B: Опубликовать в Sendgrid

Вы можете заключить все в транзакцию, чтобы этого не произошло.Нечто подобное должно сделать это.

class IncomingMail < ActiveRecord::Base

  def check_and_send(email_address)
    transaction do
      # your existing code for preventing duplicates and sending
    end
  end

end
...