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

Я хочу создать веб-службу, размещенную в Windows Azure. Клиенты будут загружать файлы для обработки, облако обработает эти файлы, создаст результирующие файлы, клиент их загрузит.

Думаю, я буду использовать веб-роли для обработки HTTP-запросов и рабочие роли для фактической обработки и что-то вроде Azure Queue или Azure Table Storage для отслеживания запросов. Предположим, что это будет хранилище таблиц Azure — одна запись «запрос» на каждый загруженный пользователем файл.

Основная проблема проектирования заключается в том, что обработка одного файла может занять от одной секунды до, скажем, десяти часов.

Итак, я ожидаю следующий случай: рабочая роль запускается, попадает в Azure Table Storage, находит запрос с пометкой «готов к обработке», помечает его как «обрабатывается», начинает фактическую обработку. Обычно он обрабатывает файл и помечает запрос как «обработанный», но что, если он неожиданно завершает работу?

Если я не позабочусь об этом, запрос навсегда останется в состоянии «обрабатывается».

Как отслеживать запросы с пометкой «в обработке», но отклоненные? Какой механизм в Windows Azure был бы наиболее удобен для этого?


person sharptooth    schedule 20.05.2011    source источник


Ответы (4)


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

Другой подход заключается в том, чтобы связать идентификацию рабочей роли с длительно работающим процессом. Рабочие роли могут сообщать о своем состоянии с помощью своего рода сердцебиения.
Если бы задания не выполнялись в течение длительного времени, вы могли бы пометить время начала задания вместо флага состояния и могли бы использовать механизм тайм-аута, чтобы определить, выполняется ли обработка. провалился.

person Chandermani    schedule 20.05.2011

Основная проблема, с которой вы столкнулись, заключается в том, что сегодня очереди не могут установить время ожидания видимости более 2 часов. Итак, вам нужен еще один механизм для индикации того, что идет активная работа. Я бы предложил аренду BLOB-объектов. Для каждого обрабатываемого файла вы арендуете либо сам большой двоичный объект, либо 0-байтовый маркерный двоичный объект. Ваши рабочие процессы сканируют доступные большие двоичные объекты и пытаются сдать их в аренду. Если они получают аренду, это означает, что она не обрабатывается, и они продолжают обработку. Если они не справляются с арендой, другой работник должен активно работать над этим.

Как только рабочий процесс завершил обработку файла, он просто копирует файл в другой контейнер в хранилище больших двоичных объектов (или удаляет его, если хотите), чтобы он не сканировался снова.

Аренда действительно ваш единственный ответ здесь, пока сообщения очереди не могут быть обновлены.

редактировать: я должен пояснить, что аренда работает здесь потому, что аренда должна активно поддерживаться каждые 30 секунд или около того, поэтому у вас есть очень маленькое окно, в котором вы знаете, умер ли кто-то или все еще работаю над этим.

person dunnry    schedule 20.05.2011
comment
Забыл о 2-часовом лимите сообщений в очереди - у меня редко есть сообщения в очереди, живущие так долго). Однако сообщения служебной шины имеют гораздо больший тайм-аут (всего несколько дней назад). - person David Makogon; 20.05.2011
comment
Будет ли счет за звонок по продлению аренды взиматься с моей учетной записи? - person sharptooth; 20.05.2011
comment
да. Каждый сделанный вами вызов REST оплачивается как транзакция. Вызов аренды - это PUT, поэтому 1 транзакция. Если вы продлеваете аренду каждые 30 секунд, потребуется почти год (на аренду), прежде чем это будет стоить вам 1 доллар (347 дней). - person dunnry; 20.05.2011

Описанная вами проблема лучше всего решается с помощью очередей Azure, поскольку хранилище таблиц Azure не предоставляет вам какого-либо механизма управления.

Используя очереди Azure, вы устанавливаете время ожидания при получении элемента очереди (по умолчанию: 30 секунд). Как только вы прочитаете элемент очереди (например, «обработать файл x, ожидающий вас в большом двоичном объекте по URL-адресу y»), этот элемент очереди становится невидимым на указанный период времени. Это означает, что другие экземпляры рабочей роли не будут пытаться захватить его одновременно. После завершения обработки вы просто удаляете элемент очереди.

Теперь: допустим, вы почти закончили и еще не удалили элемент очереди. Внезапно ваш экземпляр роли неожиданно дает сбой (или оборудование выходит из строя, или вы по какой-то причине перезагружаетесь). Код обработки элемента очереди остановлен. В конце концов, когда с момента первоначального чтения элемента очереди проходит время, эквивалентное установленному вами значению времени ожидания, этот элемент очереди снова становится видимым. Один из экземпляров вашей рабочей роли снова прочитает элемент очереди и сможет его обработать.

Несколько вещей, о которых следует помнить:

  • Элементы очереди имеют счетчик исключений из очереди. Обратите на это внимание. Как только вы достигнете определенного количества исключений из очереди для определенного элемента очереди (мне нравится использовать 3 раза в качестве моего предела), вы должны переместить этот элемент очереди в «ядовитую очередь» или табличное хранилище для автономной оценки — может быть что-то не так с сообщение или процесс обработки этого сообщения.
  • Убедитесь, что ваша обработка является идемпотентной (например, вы можете обрабатывать одно и то же сообщение несколько раз без побочных эффектов).
  • Поскольку элемент очереди может стать невидимым, а затем снова стать видимым, элементы очереди не обязательно обрабатываются в порядке FIFO.

РЕДАКТИРОВАТЬ: ответ Райана - максимальное количество сообщений очереди Azure составляет 2 часа. Сообщения очереди служебной шины имеют гораздо больший тайм-аут. Эта функция прошла CTP несколько дней назад.

person David Makogon    schedule 20.05.2011
comment
Это не подходит для моей задачи, так как я не могу придумать разумное значение по умолчанию. Обработка любой задачи может занять от одной секунды до многих часов, и это нормально. - person sharptooth; 20.05.2011
comment
Итак, почему бы просто не установить тайм-аут на 12 часов для всех элементов очереди? В худшем случае невыполненная задача (из-за сбоя) не будет повторно обработана в течение 1/2 дня. В качестве альтернативы, можете ли вы предсказать примерное значение тайм-аута до помещения его в очередь? Если это так, вы можете настроить 2 или более очередей (например, fastq, mediumq, slowq) и порождать потоки для чтения из каждой, используя тайм-ауты, скажем, 30 секунд, 1 час, 12 часов. - person David Makogon; 20.05.2011
comment
Я не могу предсказать это, и это может занять 14 часов - нет разумного верхнего предела. Какой бы таймаут я ни установил, некоторые элементы будут заблокированы на довольно длительный период. Например, пользователь загружает файл, для обработки которого требуется 30 секунд, и роль, обрабатывающая его, дает сбой. Пользователю придется ждать весь тайм-аут, прежде чем он будет повторно обработан, даже если это единственный файл в системе. - person sharptooth; 20.05.2011
comment
Мы говорим о пограничном случае. У меня были экземпляры ролей, которые запускались в течение месяца, прежде чем они были переработаны (в частности, для обновлений ОС). Просто примите это во внимание при разработке решения. Вы можете столкнуться с этим только для 2 или 3 предметов в месяц из скольких? Только вы можете решить, стоит ли это дополнительной разработки (например, превращения этого в поэтапный рабочий процесс). - person David Makogon; 20.05.2011

OnStop() вашей роли может быть частью решения, но есть некоторые обстоятельства (аппаратный сбой), когда он не будет вызываться. Чтобы покрыть этот случай, пусть ваш OnStart() пометит все с тем же RoleInstanceID как заброшенное, потому что он не будет вызываться, если что-то все еще происходит. (К счастью, вы можете заметить, что Azure повторно использует свои идентификаторы экземпляров ролей.)

person Oliver Bock    schedule 20.05.2011
comment
Звучит хорошо, но задокументировано ли повторное использование как единственно возможное поведение где-либо? - person sharptooth; 20.05.2011