Stepping out with Azure WebJobs

A while back, Microsoft Azure team announced preview of WebJobs and Hanselman blogged about it. Since then, I always wanted check out Web Jobs and finally I did it recently. And ..holy mother of god! Smile

Premise

WebJobs are cron jobs. For operation(s) that are to be performed repetitively or in a scheduled manner WebJob  is good proposition. WebJobs have been packaged along with Azure websites. The popular use case Microsoft is targeting to use WebJobs is as backend for the Websites.

Let’s say you have an e-com website and you are receiving tons of orders. For better scalability, your website (front end) would submit those order to let’s say a Azure queue. You would then have WebJob(s) configured as backend to read messages off top of the queue and process them. Or you can have a nightly cron job, which goes through the orders and sends a digest or suggestions in an email  etc. Or you can have it to do a monthly invoicing. So all those backend jobs that you do not want to perform in front end for obvious reasons can be done using WebJobs.

Even if WebJobs comes packaged along with Azure Websites – nobody is stopping us from using them without websites. For doing certain operations repetitively, Azure PaaS already offers what is termed as Worker Role. But I personally find worker roles very ceremonial. They do make sense when you want to perform long running, heavy-duty operations and you need horizontal/ vertical scaling to do that. But for doing tiny, repetitive, loopy code blocks or doing certain things in scheduled manner worker roles are expensive (time, money-wise). Worker roles are powerful, no doubt, but with great power comes great responsibility. (Can’t believe I just said that Smile) Primarily what they offer is an infinite while loop and then it’s your responsibility to implement scheduling, triggers etc.  WebJobs are light-weight, deployment-friendly and provide in-built mechanism to schedule stuff.

Implementing popular use cases using WebJobs

Conceptually, WebJob (the way I understood them) is an infinite while loop that listens for an event or trigger. You can make this listener trigger again and again continuously or you can schedule it if that’s the story you want to tell.

For all sorts of WebJobs development, Azure Web Jobs SDK and respective nuget packages needs to be pulled.

Here is an example of a WebJob that is implemented as a command line .NET exe. This one reads a message off top of a storage queue and writes that entity to the Azure table storage.  Every time a new message is available in the queue the ProcessQueueMessage() method is trigged automatically along with the respective trigger inputs.

image

Below code block shows another type of trigger that is listening on a topic/subscription. As soon as a new message is delivered to the subscription it picks up that brokered message writes it to the table storage.
image
In both examples, and instance of JobHost is created and registered in Main() which ensures the timely or scheduled execution of WebJob.

Deployment

Interestingly WebJobs support multiple ways to deliver the package. (I prefer and like the command line .NET exe, but suit yourself).Using Azure management portal you can drop a file in a certain location on the IIS box and rest is magic. Following file types are supported :

  • .exe – .NET assemblies
  • .cmd, .bat, .exe
  • .sh
  • .php
  • .py
  • .js

Once the deployment is done one can manage the WebJob – start, stop, delete etc.

Using Website => WebJobs => Add a job switch a new job can be added.

image

A WebJob can be set to run continuously or scheduled.

imageimage

Schedule can be as granular as your requirement demands. Interestingly a WebJob can be configured as recurring or as a one-time-deal as well.

imageimage

Quick word of caution. Webjobs are deployed on the IIS box, so make sure you are not doing such an operation as part of it that hogs all the memory and CPU. Good news though is it does not use IIS’s thread pool. For scaling WbJobs you need to scale your website.

Feel free to ping me in case of any help.

Advertisements

Importance of dead lettering in Azure Service Bus

Not sure we have a word called “dead lettering”. But in the below post I have used it to repetitively.Smile

In every messaging/queuing technology, there is a provision for poison queue or a mechanism to deal with bad messages. Idea is – once you are done with the message if the processing still faulters, move the message(s) aside and deal with them later. With Microsoft Azure Service Bus topics and subscriptions there is a solid provision to move such poison messages aside, so that the next set of message(s) can be picked up for processing. In Azure Service Bus world, it’s called as dead lettering the messages.

When and how should we dead letter the message?

There are many scenarios in which message are moved to dead letter implicitly and in some scenarios it’s wise to move the message to dead letter explicitly.

As for all other Azure managed services, Service Bus also throttles as it needs to protects itself from denial of service (DoS) attack. As a developer, it’s your responsibility to have retry mechanism and retry policy in place (Recommended : exponential backoff retry interval policy). One of the ways to implement it is by using Delivery Count attribute on the message itself. Delivery count on the message gets incremented every time it reads/de-queues the message off top of a subscription. Max Delivery Count can be set on subscription to make sure the retry is not happening indefinitely. Once the Max Delivery Count is reached the retry attempts can be assumed to be exhausted and message can moved to dead letter. Following screenshot shows Max Delivery Count property config for subscription.

image

In some cases we should not retry multiple times. E.g : the message itself is bad. Required attributes are missing or message is not getting serialized correctly, in such non-transient cases even if you retry multiple times the processing is going to fail every time. In scenarios like this, we can explicitly dead letter the message and save some CPU cycles.

This is how you can move messages to dead letter explicitly.

   1: if (message != null)

   2: {

   3:     message.BrokeredMessage.DeadLetter(string.Format("DeadLetter Reason {0} Error 

   4:     message {1} ", "SerializationException", ex.Message), ex.StackTrace);

   5: }

Important things to remember while dead-lettering the message

As shown in the above snippet make sure you are specifying the dead letter reason and dead letter exception details etc. which helps in obvious debugging.

Also make sure following two properties are enabled for the subscription. This would make sure the messages are dead lettered implicitly if the filter evaluation goes wrong or the message gets expired.

image

Remember, dead letter messages would not be processed until something is not done to them. The recommended practice here is to fix the messages (fix the missing attributes etc.) and move them back to the subscription. How to do that? That’s for another blog post.Smile