he ACME Toothpick Company recently implemented two transactional Windows Communication Foundation (WCF) services to integrate their toothpick manufacturing and log inventory applications. A third application, the ACME Manufacturing Manager (AMM), was subsequently developed to utilize the new services and manage the overall manufacturing process. The project was a resounding success and the toothpicks are flying off the shelves. The introduction of WCF based transactions ensured that the log and toothpick inventories stayed accurate and up-to-date.
Now, management presents ACME IT with a new challenge: chopsticks. With the recent acquisition of the Chicago Chopstick Company, ACME Toothpick Company became ACME Toothpick and Chopstick. Unfortunately for ACME IT, the toothpick manufacturing operation is located in Boston while chopstick manufacturing will remain in Chicago. The AMM application needs to communicate with the chopstick-manufacturing manager (CMM) over a potentially unreliable HTTP connection and through multiple proxy servers. ACME IT needs to guarantee messages are delivered properly and consistently between the two applications.
WCF Reliable Sessions are just what ACME IT needs. Reliable Sessions utilize the WS-ReliableMessaging protocol to ensure messages are delivered over unreliable connections. The advantage to using WS-ReliableMessaging is that the reliability is baked in at the message level rather than depending on any specific transport. Reliability is guaranteed over any type of connection and over multiple hops (i.e., through proxy servers). In addition, Reliable Sessions ensure messages are delivered in the appropriate order. You can use Reliable Sessions on HTTP, TCP, and NamedPipe transports. Because ACME IT uses WCF, implementing reliable sessions is a snap (see Figure 1).
Author’s Note: In this scenario, you want to secure your messages (A future article is planned to discuss WCF security). |
Exposing the Functionality
? | |
Figure 1. ACME?s Proposed System: An ACME employee interacts with a single system and WCF ensures message delivery.. |
The first task is to expose the functionality of the Chopstick Manufacturing Manager as a WCF-based service. The starting point is the CMM service contract, which is shown below:
[ServiceContract]public interface IChopstickBuilder{ [OperationContract] int GetChopsticksUnderConstruction(); [OperationContract] void WarmupChopstickMachine(); [OperationContract] void ConstructAChopstick();}
Notice the service contract contains a method named WarmupChopstickMachine. You must warm up the chopstick system prior to any actual manufacturing. Because of this, you must always call WarmupChopstickMachine prior to calling ConstructAChopstick. It is critical that these messages are received in the proper order. Notice there are no reliable session-specific settings on the service contract. With the contract defined, you can create the actual service implementation:
public class ChopstickBuilderService : IChopstickBuilder{ private int chopsticksInProcess = 0; public int GetChopsticksUnderConstruction() { return chopsticksInProcess; } public void WarmupChopstickMachine() { //TODO - Call to CMM API } public void ConstructAChopstick() { chopsticksInProcess++; //TODO - Call to CMM API }}
Notice that there’s nothing specific to reliable sessions in the service implementation either.The final step is to update the binding configuration for the new service in the application configuration file. The key addition is a reliableSession element, which is added to the binding configuration:
The binding configuration takes place in the secure session configuration. The reliableSession element can contain the following attributes (see Table 1).
Table 1. reliableSession Element: Attributes and Descriptions for the reliableSession element. |
Attribute | Description |
enabled | A Boolean that indicates if reliable sessions should be enabled. |
ordered | A Boolean that indicates if messages must be delivered in the order they were sent. |
inactivityTimeout | A timespan that indicates the maximum amount of a time the session can remain inactive (no messages received). The default is 10 minutes. |
Notice you have to set the ordered attribute, meaning that messages must be delivered in the order they are sent. As you will later see, no additional code is necessary because the WCF infrastructure handles the details.It is also important to understand that there are actually two timeouts. The first is the previously mentioned inactivityTimeout on the reliableSession element. The second is the receiveTimeout on the binding itself. If either of these timers elapse, the session expires. The key difference is that receiveTimeout looks for application messages only while the inactivityTimeout looks for application and infrastructure messages. An example of an application message is a call to an actual WCF service method, such as ConstructAChopstick. An example of an infrastructure message is a request to begin a sequence, as you’ll see in the remainder of this article. When using reliable sessions, be aware that you must increase or decrease both values together. The following example shows a binding configuration with both of these timeouts in use:
Having completed the WCF service, you can now update the AMM client application to use it.
private void button1_Click(object sender, EventArgs e){ ChopstickBuilderService.ChopstickBuilderClient csBuilder = new ToothpickManager.ChopstickBuilderService.ChopstickBuilderClient(); csBuilder.WarmupChopstickMachine(); csBuilder.ConstructAChopstick(); csBuilder.ConstructAChopstick(); int count = csBuilder.GetChopsticksUnderConstruction(); csBuilder.Close(); MessageBox.Show(count.ToString());}
Again, notice there is no code specific to reliable sessions. WCF handles the work for you. The last step for the client is making sure reliable sessions are enabled. Just as in the service, this is handled via a reliableSession element in the binding configuration:
Now that the client is complete, the code can be tested. Using an HTTP proxy such as Fiddler, you can examine the HTTP traffic to see exactly how the reliable sessions are handled. There are actually 11 exchanges that take place between the client and the service. The first three and last one involve WS_Trust and WS_SecureConversation negotiations, which are outside the scope of this article. Those middle seven exchanges are the most pertinent to this discussion. Taking some key data out of the actual SOAP messages, you see the following exchange in Listing 1.In plain English, the conversation from Listing 1 looks something like this:
Request: Can I please start a new sequence?
Response: Yes, here is a Sequence Identifier you can use.
Request: Here is message 1 for this sequence.
Response: Thanks, I received message 1 and have received 1 message so far.
Request: Here is message 2 for this sequence.
Response: Thanks, I received message 2 and have received 2 messages so far.
Request: Here is message 3 for this sequence.
Response: Thanks, I received message 1 and have received 3 messages so far.
Request: Here is message 4 for this sequence.
Response: Thanks, I received message 1 and have received 4 messages so far.
Request: Here is the last message.
Response: Thanks, I received message 5 and have received 5 messages so far.
Request: OK, I?m done with this sequence.
Response: I received 5 messages. Thank you, come again!
The back and forth exchange of the message number and message number acknowledgements allows WCF to ensure messages are in the proper order and, in the case of a failure to acknowledge, can be resent.Finally, it is worth discussing a few more configuration settings that can have an effect on reliable sessions. These specific attributes appear on the reliableSession element for a custom binding:
maxPendingChannels="4"/>
Table 2 outlines these values.
Table 2. reliableSession Element Custom Bindings: Attributes and Descriptions for reliableSession element custom bindings. |
Attribute | Description |
maxTransferWindowSize | This setting controls how many messages can be held for transfer at any given time. The default value is 8. |
flowControlEnabled | Enables a Microsoft proprietary implementation of flow control for WS-ReliableMessaging. The default is true. |
acknowledgementInterval | Specifies the maximum wait time before a message acknowledgement is sent. The reasoning here is that acknowledgements are not always sent immediately but can sometimes be batches to improve network performance. This value is a timespan and the default is 00:00:0.2. |
maxPendingChannels | Specifies the number of reliable sessions that can be waiting for acceptance. The default value is 4. |
maxRetryCount | Indicates how many times a message should be retried when no acknowledgment is received. The default is 8. |
reliableMessagingVersion | Specifies the version of WS-ReliableMessaging used. |
In most cases, the default values for the above settings are fine. It is, however, useful to be aware of their presence and understand their purpose. Thanks to WCF and Reliable Sessions, ACME IT quickly integrated a new application that was only reachable via an unreliable HTTP connection. WCF ensures messages are delivered properly and in a specific sequence so that the application behind those services can operate as expected. The ACME Manufacturing Manager is ready for whatever changes may come.