The WCF Routing Service is a standalone service that benefits from being hosted in AppFabric and routing to Workflow Services. It can be used to enable scenarios such as workflow service versioning, content-based routing, and routing to back up workflow services in the face of an outage.
In "Routing Messages in WCF 4," Michele Leroux Bustamante provided an introduction to the RoutingService in .NET 4 Beta 1. In this article, I apply the WCF RoutingService to Workflow Services built under .NET 4 Beta 2, and examine how to set it up and troubleshoot its configuration with AppFabric Beta 1.
Since that article was published, the major change to the WCF RoutingService was primarily that it moved from being an AppFabric (codenamed "Dublin") feature into the core of the .NET framework. Specifically, the WCF Routing Service was moved from the Microsoft.ProcessServer.Messaging assembly to the System.ServiceModel.Routing assembly. The namespace has been similarly updated to reflect that the RoutingService is now considered a part of WCF 4. Beyond that, the RoutingService has undergone a label update, with is now being consistently referred to as the router or routing service in place of the forwarding service. This last change manifests itself in the key behavior used to enable the routing service, whose element now reads “routing” instead of “forwardingBehavior.”
Setting up in AppFabric
While the RoutingService can be self hosted in a standalone process, it need to be hosted by AppFabric to take advantage of AppFabric monitoring features. The RoutingService is a WCF service, and in .NET 4 there are two approaches that one can take to host within AppFabric. Both approaches assume you have created a web application in AppFabric.
The SVC Approach
The first approach is to create an SVC endpoint by adding an SVC file to an application with the ServiceHost directive indicating the RoutingService type in the Service attribute. The ability to create SVC endpoints for WCF services was the approach one needed to take in .NET 3.x in order to host services with IIS/WAS (of which AppFabric is an evolution). Figure 1 shows the directive you would always use in an SVC file that represents a RoutingService endpoint.
Figure 1: ServiceHost directive in an SVC file
ServiceHost Service="System.ServiceModel .Routing.RoutingService, System.ServiceModel.Routing, Version=22.214.171.124, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
Configuration of the SVC hosted service goes in web.config. The association between the Service described in the SVC’s ServiceHost directive and its configuration in the web.config’s Service element is made by the name attribute on the Service element (which should be System.ServiceModel.Routing.RoutingService), as Figure 2 shows.
Figure 2: Service element in web.config that applies to RoutingService hosted in SVC file
There is additional configuration specific to the RoutingService, which we will explore after introducing the other approach to hosting the RoutingService in AppFabric.
The SVC-less Approach
The second approach is to create the service entirely via the web.config. New to .NET 4 are SVC-less service activation endpoints, which allow you to define the relative address for the endpoint. If the address you specify names an SVC file, it will appear (from the caller's perspective) for all intents and purposes as if AppFabric contains an SVC file in the applications’ file system, even though no such file would actually exist. For example, you might enable a metadata exchange endpoint on the routing service and if you were to navigate to the URL of your svc file, such as http://localhost/myService/Router.svc, you would get the expected service helper page in your browser.
The equivalent of the ServiceHost directive in the SVC file is described in web.config via the serviceActivations child element of the serviceHostingEnvironment, as Figure 3 shows. Each “virtual” service endpoint is described via an add element within the serviceActivations element. The relativeAddress attribute of the add element defines the URI of the endpoint clients will access, and when hosted within AppFabric it's always relative to the path of the containing Web application. The service attribute names the type of the service to activate (in this case the RoutingService type is provided with its assembly qualified name).
The serviceHostingEnvironment element itself must be placed as a child of the system.serviceModel element in web.config. We need some way to tie the service that is activated to its configuration. This is accomplished exactly as was done for the SVC approach in Figure 3—the service element must have a name of System.ServiceModel.Routing.RoutingService. With that association in place, we can then define the necessary behavior and endpoint configuration that enables routing.
As we will explore shortly, the RoutingService is generally enabled entirely via the web.config. In the typical deployment there are no additional assemblies or files that need to be deployed with it. This approach provides the value of having only one file to maintain to both describe the activation endpoint and configure the service—all the settings of your RoutingService router will be centrally located in web.config.
In both cases, the Application Pool used by the web application must be configured to use.NET Framework 4. You can do this within IIS Manager by selecting your web application in the Connections tree view and selecting the Basic Settings… link in the Actions pane. Next, click the Select… button on the Edit Application window. In the Select Application Pool, ensure that the pool selected in the drop down lists .Net Framework Version 4.0 in its properties (see Figure 4). If it does not, you will need to change the selected pool to one that does.
With the basics of the RoutingService hosting set up, you are now ready to begin defining how the RoutingService actually routes. This is a process that consists of the following steps:
- Define the router’s endpoints.
- Configure the routing behavior.
- Define the routing rules with filters and a filter table.
- Declare client endpoints that point to target services.
- Optionally define any backup lists of alternate services.
Sample Configuration and Workflow
As my intent is to show troubleshooting the router configuration with AppFabric monitoring, I will not exhaustively describe all of the configuration possibilities. (For more information about configuration, please see Michele Bustamante's Routing Messages in WCF 4 at and Aaron Skonnard's An Introduction to Windows Communication Foundation.) For our purposes, we will set up a very simple router that attempts to route to one workflow service which is not available. Upon receiving an EndPointNotFoundException, the routing service will try a backup workflow service which is available. We will use AppFabric monitoring to see both the failed attempt and successful attempt as a means to understand how to configure and use AppFabric monitoring to troubleshoot routing configuration problems.
For our workflow service, we will use the workflow service shown in Figure 5, which defines a stateful calculator capable of performing addition (and subtraction).
The following operations are exposed by this service:
- void Initialize (string sessionName, int initialAmount)
- void Add (string sessionName, int amount)
- int Equals (string sessionName)
The stateful part comes from the notion that the workflow service instance defines a variable called runningTotal that is initialized by the Initialize operation call and subsequently updated with every call to Add. The value of the running total is only returned when the Equals operation is called, which also causes the workflow to complete. All of the operations are correlated by the value of the sessionName property.
The complete web.config that configures both the workflow service and the routing service is shown in Figure 6. For the RoutingService configuration, notice the service element registers a basic HTTP endpoint and is configured with the routingData behavior configuration. The “routingData” behavior enables service metadata for the RoutingService’s IRequestReplyRouter contract and includes the exception details in faults so that the client can receive any faults that the router encounters in calling the target service. Most importantly, this behavior instructs the router to use the routingTable1 routing table. This table defines a single filter that matches all incoming requests and routes them to the DoesNotExist client endpoint. That filter is also configured to use a backup list called alternates, that will be used next in document order upon receiving a TimeOutException or CommunicationException derived exception (such as the EndPointNotFoundException that results in our case because Service3.xamlx does not exist) from the current endpoint. Therefore, the RoutingService will try to call Service3.xamlx, receive an EndpointNotFoundException, and then try calling Service1.xamlx. The calling client is unaware of the second attempt, and it appears as if it had just succeeded on the first try.
Using AppFabric to Diagnose the Sample
To see the RoutingService in action using AppFabric, I have defined a very simple console client. The definition of the console application’s main method is shown in Figure 7.
The key to using the routing service from the client is that the endpoint the client uses maps to the endpoint of the router service and not the workflow service. This is specified in the client’s app.config, as Figure 8 shows. Note the value of address attribute on the endpoint element. With that in mind, building and running the client just works and we get the expected result of 4 printed to the screen, but how can we examine what really took place? Let’s open up the AppFabric Dashboard.
Within IIS Manager, select the StatefulCalculator application and open the Dashboard. If we start by looking at the WF Instance History panel, as expected we see just the one activation of Service1.xamlx and can infer (because we only ran the client once) that this is also the one instance that completed successfully. Figure 9 shows the results.
This doesn’t really tell us the path the router service took to get to this endpoint, however. To get this information, we look one panel higher at the WCF Call History, as Figure 10 shows.
Here we see a little more detail. We have the expected four successful calls to the Router.svc endpoint from the client. We also, somehow, had four calls to Service1.xamlx. This view doesn't show who made those four calls to Service1.xamlx, nor our failed attempts at calling Service3.xamlx. To see this, click the Completed link in the WCF Call History tab. In the Query panel, change the Event Type from WCF Completed calls to All WCF Events, as Figure 11 shows, and then click the Run Query button.
Highlighted in the figure is the MessageSentByTransport event, which as shown in the Details pane contains a URI for Service3.xaml. This is the failed call, because now records after it indicate that the message was received. Between the last OperationInvoke and this event, the routing service is building up and attempting to make the call to Service3.xamlx. Notice that the next event above MessageSentByTransport is the ClientParameterInspectorBeforeCallInvoked—this is the router service retrying the call again on a different endpoint, which would show a URI of Service1.xamlx if the first MessageSentByTransport were selected. Immediately after (above) the first MessageSentByTransport are numerous received events coming from the Service Virtual Path of Service1.xamlx—this indicates that the routing service was successful in talking to that endpoint. The top OperationInvoked shows in the detail pane the OperationName Initialize, which is the starting operation of the workflow service.
With that pattern in mind, you can see how it is possible to use AppFabric monitoring to examine the routing attempts made by the routing service in communicating with other workflow services also hosted by the AppFabric. It is important to note that in order to see all of these events, the monitoring level for the web application must be set to Troubleshooting (which is accomplished in IIS Manager by right clicking on the web application, selecting .NET 4 WCF and WF > Configuration, clicking the Monitoring tab, and sliding the Level slider all the way up to Troubleshooting).
Streamling Routing with AppFabric
By hosting the router service in AppFabric, you get simplified deployment with only the web.config to consider, and monitoring of the RoutingService routing activity through both the Dashboard and the detailed Tracked Events views within IIS Manager.