In this lab we will go through an example of how we can pass a message from one client to a service via a queue, and process the message on the service side in a fault-tolerant way.

DevOps MPP Course Source

Pre-requisites:

Lab Tasks:

  • Fault Tolerant Application Messaging

Estimated Lab Time:

  • approx. 30 minutes

Task 1: Fault Tolerant Application Messaging

  1. Let’s start with two projects, one for the client and one for the service.
  2. Scaffold the projects with

     dotnet new console --name client && dotnet new console --name service
    
  3. Pull in the WindowsAzure.Storage .NET client package for both projects in their corresponding directories.

     dotnet add package WindowsAzure.Storage
    
  4. Create an Azure Storage account on your Microsoft Azure account, or sign up for a free one. Please see the Azure queueing tutorial for details.

  5. Let’s start with the sender. It is very simple, and in this scenario we are simply reading from the stdin and sending the arguments to the queue. Replace the code in the client project’s Program.cs as follows.

     using System;
     using System.Threading.Tasks;
     using Microsoft.WindowsAzure.Storage;
     using Microsoft.WindowsAzure.Storage.Auth;
     using Microsoft.WindowsAzure.Storage.Queue;
    
     namespace service
     {
         class Program
         {
             static void Main(string[] args)
             {
                 var storageAccount = new CloudStorageAccount(new StorageCredentials("your-accountname", "your-key"), true);
    
                 var queueClient = storageAccount.CreateCloudQueueClient();
    
                 var queue = queueClient.GetQueueReference("jobqueue");
    
                 queue.CreateIfNotExistsAsync().GetAwaiter().GetResult();
    
                 var message = new CloudQueueMessage(GetMessage(args));
    
                 queue.AddMessageAsync(message).GetAwaiter().GetResult();
    
             }
    
             private static string GetMessage(string[] args)
             {
                 return ((args.Length > 0) ? string.Join(" ", args) : "Hello World!");
             }
         }
     }
    
    
  6. Now, for the service, we will have a more elaborate scenario to demonstrate the fault tolerant processing. Here, we are expecting a series of .’s. If it is odd number of dots, we simply do not process, but it is even, we process the message. Use the following snippet for reference in your service code.

     using System;
     using System.Threading.Tasks;
     using Microsoft.WindowsAzure.Storage;
     using Microsoft.WindowsAzure.Storage.Auth;
     using Microsoft.WindowsAzure.Storage.Queue;
    
     namespace client
     {
         class Program
         {
             static void Main(string[] args)
             {
                 var storageAccount = new CloudStorageAccount(new StorageCredentials("your-accountname", "your-accountkey"), true);
    
                 var queueClient = storageAccount.CreateCloudQueueClient();
    
                 var queue = queueClient.GetQueueReference("jobqueue");
    
                 queue.CreateIfNotExistsAsync().GetAwaiter().GetResult();
    
                 var quit = false;
    
                 Console.WriteLine("Enter q and press enter to quit, just press enter to process next message.");
                 while (!quit)
                 {
                     var retrievedMessage = queue.GetMessageAsync(TimeSpan.FromSeconds(2), null, null).GetAwaiter().GetResult();
    
                     if (retrievedMessage != null)
                     {
                         var messageText = retrievedMessage.AsString;
                         Console.WriteLine($"Received: {messageText}, dequeue count is {retrievedMessage.DequeueCount}");
                         if (retrievedMessage.DequeueCount > 2)
                         {
                             Console.WriteLine("Mark the message as poison message, either move to a dead letter queue or log.");
                             queue.DeleteMessageAsync(retrievedMessage).GetAwaiter().GetResult();
                         }
                         else
                         {
                             if (messageText.Split('.').Length % 2 == 1)
                             {
                                 Console.WriteLine("Processed with success.");
                                 queue.DeleteMessageAsync(retrievedMessage).GetAwaiter().GetResult();
                             }
                             else
                             {
                                 Console.WriteLine("Received message but cannot process, has odd number of dots.");
                             }
                         }
                     }
                     else
                     {
                         Console.WriteLine("No message on the queue.");
                     }
                     quit = Console.ReadLine().Contains("q");
                 }
             }
         }
     }
    
    

Extra credit

For extra credit, you can try converting the networking communication example to use queues for communication.

Summary

In this lab you completed the following tasks:

  • Demonstrated Fault Tolerant Application Messaging