Hands-On Lab

Worker Role Communication

Lab version:2.0.0

Last updated:12/16/2018

Contents

Overview

Exercise 1: Using Worker Role External Endpoints

Task 1 – Exploring the AzureTalk Solution

Task 2 – Hosting a WCF Service in a Worker Role

Task 3 – Implementing the Chat Service

Verification

Exercise 2: Using Internal Endpoints for Inter-Role Communication

Task 1 – Creating an Inter-Role Communication Endpoint

Task 2 – Receiving Notifications from Other Worker Roles

Task 3 – Sending Notifications to Other Worker Roles

Verification

Summary

Overview

Web roles in Windows Azure provide support for HTTP and HTTPS protocols through their endpoints. For other TCP/IP protocols and ports, external endpoints allow worker roles to expose Internet-facing services over ports other than 80 and 443. These endpoints can be bound to any process and provide the means to communicate externally using a variety of TCP-based application protocols.

Similarly, for inter-role communications, internal endpoints provide a way for roles to communicate directly with each other without the need to go through queues, although queues remain the preferred method for reliable asynchronous message processing.

In this hands-on lab, you will explore internal and external endpoints by implementing a WCF chat service and host it in a Windows Azure worker role.

The AzureTalk Service

In the solution, a Windows Azure worker role hosts the WCF service, which listens on an external TCP endpoint that you configurefor this role. The service implements a duplex contract over a TCP channel that allows clients to register, send and receive messages, and receive notifications from the service over the same channel.

Figure 1

Chat service duplex contract

A typical exchange between the client application and the worker role service involves the following operations:

  1. The client application announces its presence at this chat endpoint by calling the Register operation.
  2. The client calls the GetConnectedClients operation to retrieve a list of users currently online.
  3. The client calls the SendMessage operation to send messages to other active users.
  4. The service calls the UpdateClientList operation to notify the client whenever other users connect or disconnect.
  5. The service calls the DeliverMessage operation to forward messages sent to a client by other users.

In order for the service to deliver notifications and messages from other users, the client application needs to implement a callback contract, which the service specifies in its own contract using the CallbackContract attribute.

Figure 2

Duplex service specifying its callback contract (C#)

Figure3

Duplex service specifying its callback contract (Visual Basic)

The contract for the chat service indicates that it requires sessions through its SessionMode setting. In addition, because the contract marks the Register operation as being initiating by means of the IsInitiating attribute, whenever a client invokes this particular operation, the WCF infrastructure establishes a session with the client and assigns an identifier to this session. Thereafter, and as long as the client maintains the session open, WCF assigns the same session ID to every operation invoked by the client and makes it available in the operation context through its SessionId property. The chat service uses this identifier to correlate every exchange from a particular client.

Figure 4

Service contract session requirements (C#)

Figure 5

Service contract session requirements (Visual Basic)

In addition to the WCF session, the chat service also maintains its own notion of a session, which allows it to keep track of each connected client. The service assigns a SessionInformation object to each active clientand uses it to register information about itssession. To manage sessions, the service keeps an internal dictionary of SessionInformation objects and uses the session ID assigned by WCF as the key to access the sessions it contains.

When creating a new session during client registration, the service records the session ID, a user name for the client, and a callback channel to the client. The callback channel allows the service to invoke operations on the client application including forwarding messages from peers and alerting when other users connect or disconnect. Additionally, the session contains an ID for the worker role where the client session is active. This piece of information will become significant in Exercise 2, when you implement an inter-role communication mechanism that enables communication between clients connected to different worker roles.

Figure 6

Managing sessions in the Chat Service

Because multiple clients using the service can read and update sessions concurrently, the service uses a SessionManager class to control accessto the session information dictionary in a thread-safe manner.

The code provided with the lab already contains the chat service contracts, an implementation for the Session Manager, and a client application that you can use to test the service. During the course of the lab, you will configure the internal and external endpoints of the worker role and implement the chat service.

Objectives

In this hands-on lab, you will learn how to:

  • Expose non-HTTP services in Windows Azure from a worker role through external endpoints
  • Use internal endpoints for inter-role communication

Prerequisites

The following is required to complete this hands-on lab:

  • IIS 7 (with ASP.NET, WCF HTTP Activation)
  • Microsoft .NET Framework 4.0
  • Microsoft Visual Studio 2010
  • Windows Azure Tools for Microsoft Visual Studio 1.6

Setup

In order to execute the exercises inthis hands-on lab you need to set up your environment.

  1. Open a Windows Explorer window and browse to the lab’sSourcefolder.
  2. Double-click the Setup.cmd file in this folder to launch the setup process that will configure your environment and install the Visual Studio code snippets for this lab.
  3. If the User Account Control dialog is shown, confirm the action to proceed.

Note: Make sure you have checked all the dependencies for this lab before running the setup.

Using the Code Snippets

Throughout the lab document, you will be instructed to insert code blocks. For your convenience, most of that code is provided as Visual Studio Code Snippets, which you can use from within Visual Studio 2010 to avoid having to add it manually.

If you are not familiar with the Visual Studio Code Snippets, and want to learn how to use them, you can refer to the Setup.docx document in the Assets folder of the training kit, which contains a section describing how to use them.

Exercises

This hands-on lab includes the following exercises:

  1. Using Worker Role External Endpoints
  2. Using Internal Endpoints for Inter-Role Communication

Estimated time to complete this lab: 60 minutes.

Note:When you first start Visual Studio, you must select one of the predefined settings collections. Every predefined collection is designed to match a particular development style and determines window layouts, editor behavior, IntelliSense code snippets, and dialog box options. The procedures in this lab describe the actions necessary to accomplish a given task in Visual Studio when using the General Development Settings collection. If you choose a different settings collection for your development environment, there may be differences in these procedures that you need to take into account.

Exercise 1: Using Worker Role External Endpoints

During this exercise, you will implement the WCF chat service. This involves defining an external endpoint for the worker role, implementing the service contract and updating the worker role to host the service at the external endpoint.

Windows Azure allows you to create as many instances of a worker role as you require, which means that you are able to host the chat service in many different nodes simultaneously. However, in this initial implementation, each instance maintains its own list of sessions. This allows clients connected to the same worker role to communicate with each other but prevents them from exchanging messages with peers that have active sessions in other worker roles. In the next exercise, you will see how to communicate worker roles and exchange session information between them.

Figure 7

Clients can only communicate with peers connected to the same worker role

Task 1 – Exploring the AzureTalk Solution

In this task, you open the starting solution and become familiar with the code.

  1. Open Visual Studioin elevated administrator mode from Start | All Programs | Microsoft Visual Studio 2010 by right clicking the Microsoft Visual Studio 2010 shortcut and choosing Run as administrator.
  2. In the File menu, choose Open and then Project/Solution. In the Open Project dialog, browse to Ex1-WorkerExternalEndPoints\Beginin the Sourcefolder of the lab, select Begin.sln in the folder for the language of your preference (Visual C# or Visual Basic) and click Open.
  3. The solution contains the following projects:

Figure 8

Solution Explorer showing the AzureTalk Visual C# solution

Figure 9

Solution Explorer showing the AzureTalkVisual Basic solution

AzureTalk / A standard Windows Azure project configured to support a single worker role named AzureTalk.Service.
AzureTalk.Client / A WPF client application that can connect to the chat service to exchange messages with peers. It implements the service callback contract and can receive notifications from the service. In this hands-on lab, you will use this application to test the chat service.
AzureTalk.Contract / A class library project that contains the service and data contracts for the chat service and the callback contract implement by the client application. The clientapplication and the service share this project.
AzureTalk.Service / A worker role that hosts the chat service and listens over an external TCP endpoint.

Task 2 – Hosting a WCF Service in a Worker Role

In this task, you configure the worker role to define an external endpoint and then create a WCF service host to listen at this endpoint.

  1. Add an external endpoint definition to the worker role. In the role Propertieswindow, change to the Endpoints tab and click Add Endpoint. Set the name of the new endpoint to “ChatService”, leave the Type as “Input” and the Protocol as “tcp”, and then set the Port number to the value “3030”. The worker role will use this TCP endpoint to host the chat service.

Figure 10

Defining the external endpoint for the worker role

  1. Press CTRL + S to save the changes to the worker role configuration.
  2. Open the WorkerRole.cs file(for Visual C# projects) or WorkerRole.vbfile (for Visual Basic projects)in the AzureTalk.Service project. This file contains the entry point of the worker role.
  3. In the WorkerRole class, define a WCF ServiceHostmember field.

(Code Snippet –Windows Azure Worker Role Communication – Ex01 ServiceHost- CS)

C#

///<summary>ServiceHost object for internal and external endpoints.</summary>

privateServiceHost serviceHost;

(Code Snippet –Windows Azure Worker Role Communication – Ex01 ServiceHost- VB)

Visual Basic

''' <summary>ServiceHost object for internal and external endpoints.</summary>

Private serviceHost As ServiceHost

  1. Add the StartChatService method to the WorkerRole class. This method creates and configures the WCF service host instance for the chat service.

(Code Snippet –Windows Azure Worker Role Communication – Ex01 StartChatService - CS)

C#

///<summary>

/// Starts the service host object for the internal

/// and external endpoints of the chat service.

///</summary>

///param name="retries">Specifies the number of retries to

/// start the service in case of failure.</param

privatevoidStartChatService(int retries)

{

// recycle the role if host cannot be started

// after the specified number of retries

if (retries == 0)

{

RoleEnvironment.RequestRecycle();

return;

}

Trace.TraceInformation("Starting chat service host...");

this.serviceHost = newServiceHost(typeof(ChatService));

// Recover the service in case of failure.

// Log the fault and attempt to restart the service host.

this.serviceHost.Faulted += (sender, e) =>

{

Trace.TraceError("Host fault occured. Aborting and restarting the host. Retry count: {0}", retries);

this.serviceHost.Abort();

this.StartChatService(--retries);

};

// use NetTcpBinding with no security

NetTcpBinding binding = newNetTcpBinding(SecurityMode.None);

// define an external endpoint for client traffic

RoleInstanceEndpointexternalEndPoint =

RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["ChatService"];

this.serviceHost.AddServiceEndpoint(

typeof(IChatService),

binding,

string.Format("net.tcp://{0}/ChatService", externalEndPoint.IPEndpoint));

try

{

this.serviceHost.Open();

Trace.TraceInformation("Chat service host started successfully.");

}

catch (TimeoutExceptiontimeoutException)

{

Trace.TraceError(

"The service operation timed out. {0}",

timeoutException.Message);

}

catch (CommunicationExceptioncommunicationException)

{

Trace.TraceError(

"Could not start chat service host. {0}",

communicationException.Message);

}

}

(Code Snippet –Windows Azure Worker Role Communication – Ex01 StartChatService - VB)

Visual Basic

''' <summary>

''' Starts the service host object for the internal

''' and external endpoints of the chat service.

''' </summary>

''' <param name="retries">Specifies the number of retries to

''' start the service in case of failure.</param

PrivateSubStartChatService(ByVal retries AsInteger)

' recycle the role if host cannot be started

' after the specified number of retries

If retries = 0 Then

RoleEnvironment.RequestRecycle()

Return

EndIf

Trace.TraceInformation("Starting chat service host...")

Me.serviceHost = NewServiceHost(GetType(ChatService))

' Recover the service in case of failure.

' Log the fault and attempt to restart the service host.

AddHandlerMe.serviceHost.Faulted, Sub(sender, e)

Trace.TraceError("Host fault occured. Aborting and restarting the host. Retry count: {0}", retries)

Me.serviceHost.Abort()

retries -= 1

Me.StartChatService(retries)

EndSub

' use NetTcpBinding with no security

Dim binding AsNewNetTcpBinding(SecurityMode.None)

' define an external endpoint for client traffic

DimexternalEndPointAsRoleInstanceEndpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints("ChatService")

Me.serviceHost.AddServiceEndpoint(GetType(IChatService), binding, String.Format("net.tcp://{0}/ChatService", externalEndPoint.IPEndpoint))

Try

Me.serviceHost.Open()

Trace.TraceInformation("Chat service host started successfully.")

CatchtimeoutExceptionAsTimeoutException

Trace.TraceError("The service operation timed out. {0}", timeoutException.Message)

CatchcommunicationExceptionAsCommunicationException

Trace.TraceError("Could not start chat service host. {0}", communicationException.Message)

EndTry

EndSub

Note: The StartChatService method creates and configures a service host to expose thechat service using the implementation provided by the ChatService class.

The code configures a single endpoint for the contract defined by the IChatService interfacein the AzureTalk.Contract project using aNetTcpBinding binding to enable TCP message delivery using a binary encoding. For this service, the binding configuration specifies no transport security.

To determinethe service endpoint address, the method uses the RoleEnvironmentto obtain a reference the “ChatService” endpoint for the current instance, which you previously defined for the worker role. Note that this address is the internal address as seen by the worker role instance located behind the load balancer.

To provide a certain degree of fault tolerance, the method subscribes to the Faulted event of the service host to restart the service in case of failure and attempts its recovery by re-starting the host. After a number of failed retries, the worker role requests to be recycled.

  1. Next, update the Run method of the worker role to createand start the chat service. To do this, insert a call to the StartChatService method as shown (highlighted) in the code below.

C#

publicoverridevoid Run()

{

Trace. TraceInformation("AzureTalk.Service entry point called.");

this.StartChatService(3);

while (true)

{

Thread.Sleep(300000);

Trace.TraceInformation("Working...");

}

}

Visual Basic

PublicOverridesSub Run()

Trace.TraceInformation("AzureTalk.Service entry point called.")

Me.StartChatService(3)

Do

Thread.Sleep(300000)

Trace.TraceInformation("Working...")

Loop

EndSub

  1. Press CTRL + S to save the changes to the file.

Task 3 – Implementing the Chat Service

In this task, you implement the chat service as specified in the contract defined by the IChatService interface of the AzureTalk.Contract project.

  1. Open ChatService.cs(for Visual C# projects) or ChatService.vb(for Visual Basic projects) in the AzureTalk.Service project. This file contains a skeleton implementation of the chat service contract. In the next steps, you will implement the service operations.
  2. Locate the Register operation and replace its body with the following code.

(Code Snippet –Windows Azure Worker Role Communication – Ex01Register - CS)

C#

///<summary>

/// Called by clients to announce they are connected at this chat endpoint.

///</summary>

///<param name="userName">The user name of the client.</param>

///<returns>The ClientInformation object for the new session.</returns>

publicClientInformation Register(string userName)

{

// retrieve session information

string roleId = RoleEnvironment.CurrentRoleInstance.Id;

string sessionId = OperationContext.Current.SessionId;

IClientNotification callback = OperationContext.Current.GetCallbackChannel<IClientNotification>();

SessionInformation session;