Не так давно в Microsoft Azure появилась новая фича — WebJob, правда, пока в стадии alpha 2.
Основная идея WebJob — дать возможность запускать в Azure задачи по расписанию. Плюс, для .NET кода предоставляется простой API для event driven обработки.
Решения до WebJob
Если было действие, которое нужно запускать раз в день то раньше это решалось несколько странно для Cloud Platform:
Вариант 1:
Создать виртуалку, и в Windows Scheduler поставить новую задачу. Этот вариант отлично работает, но в рамках виртуальной машины. Если нужно, например, логи сайта с WebSite Role сжимать и отправлять куда-нибудь, то виртуалка абсолютно бесполезна. Есть конечно и плюс — нет привязки к Azure.
Вариант 2:
Планировщик Windows Azure Scheduler. Пример по русски . Проблема в том, что для его использования надо написать код, который, в общем-то, лично мне кажется не обязательным: все должно быть проще.
Таким образом, можно запустить .NET код, но что делать, если логика написана на батниках или на powershell?
Ну и самое важное: сервис предполагается использовать для:
- Invoking a Web Service over HTTP/s
- Post a message to a Windows Azure Storage Queue
Такой набор мне кажется очень ограниченным.
Вариант 3:
Worker Role, которая в активном режиме будет жить и по заложенному вами алгоритму, выполнять действия. Есть один момент: такой подход совсем не Event Driven. Так, можно запустить .NET код, но что делать, если код опять же на батниках или на powershell? Ну и еще один момент: т.к. Worker Role — это инстанс, за который надо платить, а не отдельно стоящий .exe файл к вашему WebSite Role.
Что же может предложить WebJob, чего не предлагают все выше перечисленные варианты?
Запуск exe, bat, sh, ps файлов по расписанию или прямо из web-интерфейса.
Для .NET WebJob дополнительно дает API, связывающий ваш код, с внешними источниками событий (очередями, таблицами, блобами). Это Api является не обязательным, но дает плюшку в виде — окна во внешний мир, позволяющее реагировать на события.
Предварительные настройки:
Запустить все это можно и локально, без деплоя на Azure, но давайте это сделаем по-честному — загрузим в Azure. Для этого нам понадобится:
- Создать аккаунт в Azure. Я взял Trial на 30 дней;
- Создать Web Site;
- Создать Storage.
Типы Web Job
WebJob можно разделить на 3 типа:
- On Demand Task — по требованию (ручной запуск: после загрузки появляется кнопка «Запустить»);
- Continuously Running Task — постоянно работающие задачи (после загрузки zip архива стартует автоматически и живет вечно, а .NET код реагирует на появление новых файлов в очереди);
- Scheduled Task — запускаемые по расписанию
Я этого делать не буду, об этом более подробно можно прочесть тут.
Мониторинг
Типичные решения на Windows, как то: Windows service или задача в Windows scheduler имеют одну общую проблему — никогда не знаешь работают они или нет, пока не глянешь на список процессов. Не раз натыкался на ситуацию, когда сервис умирал, но т.к. его через WebUi не видно, то узнаешь о его падении по косвенным признакам (как всегда — логи, крики пользователей, отвалился функционал в UI). Написание WatchDog — это конечно решение, но надо писать код и проверять, что Watchdog сам по себе работает.
Еще одной проблемой является- а запускался ли он по расписанию? Это можно понять из логов, но их же читать надо.
На этом базовая фича- запуск исполняемого файла по расписанию закончена.
Привязки через Queue (очереди), Blobs (блобы)
Рассмотрим самый тривиальный пример:
Через nuget установлены 2 пакета:
- Install-Package Microsoft.WindowsAzure.Jobs -Pre;
- Install-Package Microsoft.WindowsAzure.Jobs.Host -Pre.
Они за собой еще потянули Newtonsoft.Json и Microsoft.WindowsAzure.ConfigurationManager, но это мелочи.
В методе main создаем объект JobHost и вызываем метод RunAndBlock().
Больше никакой логики при запуске можно не создавать. Как мы видим, из Main никаких других вызовов, кроме RunAndBlock нет.
При загрузке в Azure система сама распознает методы, у которых входные параметры размечены атрибутами типа *Input (например, QueueInput) и вызывает эти методы. Т.е. окно во внешний мир за нас уже прорубили. Наша задача — отработать входное сообщение.
Как и когда Azure понимает, что нужно вызвать метод?
Azure дергает метод, когда в соответствующую очередь/таблицу/блоб добавляется новое значение. Получается такой Event Driven стиль. При этом нам не надо заморачиваться с API чтением объектов из blob, queue, table: за нас инфраструктура WebJob сделает это сама.
Я специально сделал этот пример с одной неточностью, чтобы показать что мы увидим в логах. Выходная строка должна быть out string output – такова специфика.
Чтобы показать, как он работает:
- я установил Azure Storage Explorer.
- Создал 2 очереди: myqueye и myqueuecopy.
Binding (привязка) параметров
Хорошая статья про Binding (привязка) параметров, где подробно рассказано об Input параметрах.
Из интересного:
1. Если у метода есть 2 *Input аргумента, то он будет вызван по добавлению нового объекта в первую очередь/блоб/таблицу, а при добавлении во вторую — нет.
2. Можно использовать не только BlobInput и BlobOutput атрибуты, но и механизм, схожий с routing в mvc/webAPI.
3. Не только Stream или строка.
Дополнительные ссылки
- Примеры кода с codeplex
- Собранние интересных ссылок
- Блог Хансельмана
- Анонс на msdn
- How to на ASP.NET
- как хранятся webjob физически.
- Расширение к студии, добавляющее кнопку “сделать из консольника webjob”.
- человек сделал систему мониторинга сайта на webjob. Хотя я бы ни за что так делать не стал, но как пример кода глянуть стоит.
Ссылка на примеры описанные выше на github. Строки подключения к Storage не действительные, они оставлены как образец, чтобы понять как они выглядят.
P.S. Для тех, кто читает Хансельмана или блог команднды asp.net. Я, по сути, повторил то, что сделали они, но добавил, чем это решение отличается от того, что было ранее.
Автор: SychevIgor