Azure Inter-role communication using callback instead of queues

I’m currently playing with Azure and the Azure training kit, and I learned something cool today. When you work with Azure you can setup multiple worker roles for your Azure application. If you want to make these roles talk to one another you can use the queuing mechanism which is part of Azure. But you can also use WCF dual interface mechanism. Imagine you want to build a chat application using Azure and WCF. In this case you define a worker role that exposes a dual interface like this:

Code Snippet
  1. [ServiceContract(
  2.     Namespace = "urn:WindowsAzurePlatformKit:Labs:AzureTalk:2009:10",
  3.     CallbackContract = typeof(IClientNotification),
  4.     SessionMode = SessionMode.Required)]
  5. public interface IChatService
  6. {
  7.   /// <summary>
  8.   /// Called by client to announce they are connected at this chat endpoint.
  9.   /// </summary>
  10.   /// <param name="userName">The user name of the client.</param>
  11.   /// <returns>The ClientInformation object for the new session.</returns>
  12.   [OperationContract(IsInitiating = true)]
  13.   ClientInformation Register(string userName);
  14.  
  15.   /// <summary>
  16.   /// Sends a message to a user.
  17.   /// </summary>
  18.   /// <param name="message">The message to send.</param>
  19.   /// <param name="sessionId">The recipient's session ID.</param>
  20.   [OperationContract(IsInitiating = false)]
  21.   void SendMessage(string message, string sessionId);
  22.  
  23.   /// <summary>
  24.   /// Returns a list of connected clients.
  25.   /// </summary>
  26.   /// <returns>The list of active sessions.</returns>
  27.   [OperationContract(IsInitiating = false)]
  28.   IEnumerable<ClientInformation> GetConnectedClients();
  29. }

The IClientNotification interface is the call-back interface which is implemented by the client of the service. The client calls the Register method on the server, which then can keep track of the client by using the callback interface:

Code Snippet
  1. IClientNotification callback =
  2.   OperationContext.Current.GetCallbackChannel<IClientNotification>();

 

If you host the service as a single instance, all clients will register to the same service, so this service can easily track each client. But if you grow and start using multiple instances of your service in Azure, each client will register to a single instance, so each instance will know only about its own clients. If two clients, registered to different instances, want to communicate, the services will have to handle the communication for this. The solution is easy, make them also expose the IClientNotification callback service interface using internal endpoints, so they can communicate to each other:

Code Snippet
  1. public class ChatService : IChatService, IClientNotification

 

Of course each service will have to be able to find the other service instances. This you can do with the RoleEnvironment class, which you can use in your worker role class:

Code Snippet
  1. var current = RoleEnvironment.CurrentRoleInstance;
  2. var endPoints = current.Role.Instances
  3.                 .Where(instance => instance != current)
  4.                 .Select(instance => instance.InstanceEndpoints["NotificationService"]);

 

This does require the worker role to define an internal endpoint. You can do this in Visual Studio 2010. Select the worker role’s properties, go to the endpoint tab and enter an internal endpoint:

image

The rest of the code is straightforward (of your comfortable with WCF that is) and can be found in the Azure Training Kit (look for the Worker Role Communication lab).