#azure #reliability #azure-worker-roles
#azure #надежность #azure-worker-roles
Вопрос:
Я хочу создать веб-службу, размещенную в Windows Azure. Клиенты будут загружать файлы для обработки, облако обработает эти файлы, создаст результирующие файлы, клиент загрузит их.
Я предполагаю, что буду использовать веб-роли для обработки HTTP-запросов и рабочие роли для фактической обработки и что-то вроде Azure Queue или Azure Table Storage для отслеживания запросов. Давайте представим, что это будет хранилище таблиц Azure — одна запись «запроса» на загруженный пользователем файл.
Основная проблема проектирования заключается в том, что обработка одного файла может занять от одной секунды до, скажем, десяти часов.
Итак, я ожидаю следующий случай: запускается рабочая роль, попадает в хранилище таблиц Azure, находит запрос с пометкой «готов к обработке», помечает его «обрабатывается», запускает фактическую обработку. Обычно файл обрабатывается и запрос помечается как «обработанный», но что, если он неожиданно завершается?
Если я не позабочусь об этом, запрос навсегда останется в состоянии «обрабатывается».
Как мне отслеживать запросы, помеченные как «обрабатывается», но оставленные? Какой механизм в Windows Azure был бы наиболее удобным для этого?
Ответ №1:
Основная проблема, с которой вы сталкиваетесь, заключается в том, что очереди не могут установить время ожидания видимости, превышающее 2 часа сегодня. Итак, вам нужен другой механизм, чтобы указать, что выполняется активная работа. Я бы предложил арендовать большой двоичный объект. Для каждого обрабатываемого файла вы либо арендуете сам большой двоичный объект, либо большой двоичный объект с маркером 0 байт. Ваши работники сканируют доступные большие двоичные объекты и пытаются арендовать их. Если они получают аренду, это означает, что она не обрабатывается, и они продолжают обрабатывать. Если они завершают аренду с ошибкой, другой работник должен активно работать над этим.
Как только рабочий завершит обработку файла, он просто копирует файл в другой контейнер в хранилище больших двоичных объектов (или удаляет его, если хотите), чтобы он не сканировался повторно.
Аренда — это действительно ваш единственный ответ здесь, пока сообщения очереди не могут быть возобновлены.
Редактировать: Я должен уточнить, что причина, по которой аренда будет работать здесь, заключается в том, что аренда должна активно поддерживаться каждые 30 секунд или около того, поэтому у вас есть очень маленькое окно, в котором вы узнаете, умер ли кто-то или все еще работает над этим.
Комментарии:
1. Забыл о 2-часовом лимите очереди сообщений — у меня редко бывают сообщения в очереди, живущие так долго). Однако сообщения служебной шины имеют гораздо большее время ожидания (выпущено всего несколько дней назад).
2. Будет ли счет за вызов «продлить аренду» списываться с моей учетной записи?
3. ДА. Каждый выполняемый вами вызов REST оплачивается как транзакция. Вызов lease — это PUT, то есть 1 транзакция. Однако, если вы продлеваете аренду каждые 30 секунд, потребуется почти год (на аренду), прежде чем это обойдется вам в 1 доллар (347 дней).
Ответ №2:
Я считаю, что эта проблема не зависит от технологии.
Поскольку ваши задания по обработке выполняются долго, я предлагаю, чтобы эти задания сообщали о ходе выполнения. Таким образом, задание, о ходе выполнения которого не сообщалось в течение значительного периода времени, становится явным кандидатом на очистку, а затем может быть перезапущено на другой рабочей роли.
Как вы регистрируете прогресс и выполняете замену заданий, зависит от вас. Один из подходов заключается в использовании базы данных в качестве механизма записи и создании рабочего процесса агента, который выполняет пинг таблицы выполнения задания. В случае, если рабочий процесс обнаружит какие-либо проблемы, он может предпринять корректирующие действия.
Другим подходом было бы связать идентификацию рабочей роли с длительным процессом. Рабочие роли могут сообщать о своем состоянии работоспособности, используя своего рода биение сердца.
Если бы задания выполнялись недолго, вы могли бы вместо этого пометить время начала задания флагом состояния и могли бы использовать механизм тайм-аута, чтобы определить, произошел сбой обработки.
Ответ №3:
Описанная вами проблема лучше всего решается с помощью очередей Azure, поскольку хранилище таблиц Azure не предоставляет вам никакого механизма управления.
Используя очереди Azure, вы устанавливаете тайм-аут при получении элемента очереди (по умолчанию: 30 секунд). Как только вы прочитаете элемент очереди (например, «файл обработки x ожидает вас в blob-двоичном объекте по url y»), этот элемент очереди становится невидимым на указанный период времени. Это означает, что другие экземпляры рабочей роли не будут пытаться перехватить ее одновременно. После завершения обработки вы просто удаляете элемент очереди.
Теперь: допустим, вы почти закончили и еще не удалили элемент очереди. Внезапно ваш экземпляр роли неожиданно выходит из строя (или происходит сбой оборудования, или вы перезагружаетесь по какой-либо причине). Код обработки элементов очереди теперь остановлен. В конце концов, когда с момента первоначального чтения элемента очереди проходит время, эквивалентное заданному вами значению тайм-аута, этот элемент очереди снова становится видимым. Один из ваших экземпляров рабочей роли еще раз прочитает элемент очереди и сможет обработать его.
Несколько вещей, которые следует иметь в виду:
- Элементы очереди имеют количество удалений из очереди. Обратите на это внимание. После того, как вы нажмете определенное количество удалений из очереди для определенного элемента очереди (мне нравится использовать 3 раза в качестве моего ограничения), вам следует переместить этот элемент очереди в «опасную очередь» или табличное хранилище для автономной оценки — возможно, что-то не так с сообщением или процессом обработки этого сообщения.
- Убедитесь, что ваша обработка идемпотентна (например, вы можете обрабатывать одно и то же сообщение несколько раз без побочных эффектов)
- Поскольку элемент очереди может стать невидимым, а затем вернуться к видимости позже, элементы очереди необязательно обрабатываются в порядке FIFO.
РЕДАКТИРОВАТЬ: Согласно ответу Райана — Сообщения в очереди Azure не превышают 2-часовой тайм-аут. Время ожидания сообщений из очереди служебной шины намного больше. Эта функция была запущена CTP всего несколько дней назад.
Комментарии:
1. Это не соответствует моей задаче, поскольку я не могу найти разумное значение по умолчанию. Обработка любой задачи может занять от одной секунды до многих часов, и это нормально.
2. Итак, почему бы просто не установить время ожидания равным 12 часам для всех элементов очереди? Наихудший сценарий заключается в том, что неудачная задача (из-за сбоя) не будет повторно обрабатываться в течение 1/2 дня. В качестве альтернативы, можете ли вы предсказать приблизительное значение времени ожидания до помещения его в очередь? Если это так, вы можете настроить 2 или более очередей (например, fastq, mediumq, slowq) и запускать потоки для чтения из каждой, используя тайм-ауты, скажем, 30 секунд, 1 час, 12 часов.
3. Я не могу это предсказать, и это также может занять 14 часов — нет разумного верхнего предела. Независимо от того, какое время ожидания я установил для некоторых элементов, они будут заблокированы на довольно длительный период. Например, пользователь загружает файл, на обработку которого требуется 30 секунд, и роль, обрабатывающая его, выходит из строя. Пользователю придется подождать весь тайм-аут, прежде чем он будет повторно обработан, даже если это единственный файл в системе.
4. Мы говорим о пограничном случае. Экземпляры ролей запускались в течение месяца, прежде чем были переработаны (специально для обновлений ОС). Просто примите это во внимание при разработке вашего решения. Вы можете столкнуться с этим только для 2 или 3 элементов ежемесячно из скольких? Только вы можете решить, стоит ли это дополнительной разработки (например, превращения этого в поэтапный рабочий процесс).
Ответ №4:
Функция onStop () вашей роли может быть частью решения, но при некоторых обстоятельствах (аппаратный сбой) она не вызывается. Чтобы учесть этот случай, пусть ваша функция OnStart () пометит все тем же RoleInstanceID как заброшенное, потому что она не была бы вызвана, если бы что-то все еще происходило. (К счастью, вы можете заметить, что Azure повторно использует идентификаторы экземпляров своей роли.)
Комментарии:
1. Звучит заманчиво, но задокументировано ли это повторное использование как единственно возможное поведение где-либо?