Web ServicesA Windows Service Solution for Unreliable Web Services

A Windows Service Solution for Unreliable Web Services

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Using the Internet to solve integration problems can be an adventure. If you’ve experimented with Internet Web services integration, you know reliability is a big issue. The source of the problem can be anywhere between your potentially unreliable Internet connection and the hosting vendor’s possibly overloaded server. You can make network- and Internet-access improvements on your end, but what do you do to fix the vendor’s part of the problem?

This article explains an approach for addressing Web service reliability issues. It first introduces a strategy for addressing the problem and then takes a deep dive into the solution.

A Strategy to Mitigate the Problem

The underlying strategy to mitigate the problem is to isolate the Internet Web service code from an application and centralize access to the external Web service so it can be more easily troubleshot and reconfigured. Here are the solution objectives:

  • Confine the Web services code to a single place where it can be easily monitored, administered, reconfigured, and troubleshot. Speed is an issue, but it can be sacrificed for robustness.
  • Decouple the application from the Internet Web service. Remove Internet Web service code from the application using the Web service. The application should be concerned only with sending and processing the results of the Web service, not with configuration and error handling.
  • If the Web service goes down, allow the application to continue functioning normally.
  • Make the solution reusable. Multiple Web services will be invoked by many different parts of the application.

Many tools have made invoking a Web service as simple as making a synchronous function call in your application. The key to addressing the Web service reliability issue is abandoning the synchronous function call notion and thinking asynchronously.

Asynchronous Messaging

Asynchronous messaging is an integration approach extensively covered in the book Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions. A complete discussion of asynchronous messaging is beyond the scope of this article, so I’ll summarize the key points pertaining to the solution.

In asynchronous messaging, a sender transmits data known as a “message” and a receiver consumes it. A transmitted message moves from sender to receiver through channels. Channels are built using databases, message queues, file systems—anything capable of persisting and sharing data.

A message is composed of two things:

  • A header, which contains things like processing instructions, information about the structure of the message, and the ultimate message destination
  • A body, which contains the message data

A message can take any physical form: XML, a record in a database, a serialized class, a file, and so forth.

To understand the basic idea behind asynchronous messaging, look at the synchronous Web service example at a high level and examine how asynchronous messaging differs.

When calling a Web service synchronously, the consumer (caller) performs all the following actions in the same running process:

  • Gathers values for the Web service parameters
  • Locates the Web service
  • Connects to the server hosting the Web service
  • Calls the Web service
  • Handles any errors
  • Processes the reply from the Web service

Being synchronous, the actions above take an all-or-nothing approach. All of the actions must happen successively, successfully, and in a timely fashion to complete the process.

Asynchronous messaging is different. Each action or group of actions can be handled by a separate process or class. So, for example, one process may handle collecting and packaging the parameters and then post the packaged parameters to a channel to be picked up by another process that invokes the Web service.

Each class or process is responsible only for performing its assigned segment in the process. Unlike the all-or-nothing approach, a single process cannot fail all segments. If it sounds like object-oriented design, it’s because it is like object-oriented design—only on a larger scale.

So, how do you apply an asynchronous message to fix the unreliable Web service problem?

The Asynchronous Message Solution

Applying lessons from the Enterprise Integration Patterns book and using notation from it, Figure 1 shows a design that outlines the solution.

Figure 1. A Design Outlining the Solution

Note the multiple channels, endpoints, and gateways, but only one router. Also note that it uses the database symbol to show that the gateway accesses the database of the application. Another way of expressing this is to use the “Claim Check” symbol.

Using the Figure 1 design achieves the following objectives:

  • Decoupling, handling is moved to a specialized Windows service outside of the application
  • Reusability

Now, see how the company I work for implemented the design.

Service Overview

Traditional integration projects utilize some piece of middleware or message queue application. The endpoints and channels for my company’s service were implemented using Transact SQL and SQL Server. Because my company’s applications are all SQL Server-based, SQL Server technologies was a natural choice for easy integration with our application environment.

The technology behind the solution functions as follow:

  1. Applications write some standard fields to tables (channels) on the server.
  2. The router reads the table (channel) messages using stored procedures. (The router is a Windows service, and the gateways are all implemented using a .NET interface class inside of a separate assembly.)

Because the router is the heart of the solution, you should focus on the router implementation.

Router: The Heart of the Solution

The router consists of the classes in Figure 2, which depicts their hierarchical relationship.

Figure 2. Hierarchical Relationship of Router Classes

The classes have the following roles:

  • GatewayRouter performs all of the work, reading the channel information and loading/invoking the appropriate XmlServiceGateway contained inside a particular assembly.
  • GatewayRouterController spins threads and handles the stopping and starting of the Windows service application.
  • GatewayRouterExecution executes the GatewayRouter on one of the controller’s threads until the signaling class housed inside the controller signals it to stop.
  • ServiceWindowChecker also executes on a thread contained in the controller and continually checks the computer’s time. The checker signals other parts of the application when the Windows service has moved out of the service window time. Servers are more likely to be functioning when humans are present monitoring their uptime. A service window function allows you to control when a Web service is invoked.

Channel location information and gateway information are loaded in the config file of the Windows service. You can download the source code, so I’m going to focus only on the key functions in the service.

Loading a Gateway

As discussed previously, the GatewayRouter performs all of the routing functions, including executing the appropriate gateway. To initiate routing, the GatewayRouterExecution calls Init and then DoRouting in GatewayRouter. DoRouting calls RouteMessageFor on each of the configured channels. Each channel can have multiple messages, so RouteMessageFor calls InvokeGateway for each channel message.

GatewayRouter is the heart of the Windows service and the heart of GatewayRouter is the InvokeGateway function:

IXmlServiceGateway gateway = null;
bool tryWSInvocation = true;
int tryCount = 0;
   gateway = GetGateway(info);
   while ( tryWSInvocation )
      //The assembly can indicate that a retry is possible,
      //the router determines how many times it will attempt to
      //call run.
      if (gateway.CanRetryRun() && tryCount < _wsRetryCount)
         tryWSInvocation = true;
         tryWSInvocation = false;
   //This was added for administration troubleshooting and reporting
   WriteGatewayResultsToDB (dbConn,info,gateway.CurrentMessage);
   if (gateway.IsErrorToReport() )

As you can see, code is included to retry the Run function should some sort of failure occur.

The Windows service assumes all gateways inherit from a common C# interface: IXmlServiceGateway. On a class implementing IXmlServiceGateway, the Run function performs all the actions necessary to invoke the Web service and write the response data back to the application database. Giving the gateway access to a database so it could retrieve parameters and save responses greatly simplified the process, allowed for easier transaction processing, and eliminated the need to pass XML messages between the queues.

Another key section of code is the AddGateway function:

Assembly assm = Assembly.LoadFrom(info.AssemblyName);
//Assembly has no public constructor
IXmlServiceGateway gateway;
gateway = null;
gateway = (IXmlServiceGateway) assm.CreateInstance(info.ClassNameSpace);
_gateways.Add (gateway);

AddGateway uses functions from the System.Reflection namespace to load the assembly containing the Gateway class, which creates an instance of the Gateway class and assigns the instance to an IXmlServiceGateway interface.

Controller: Multithreading

GatewayRouterExecution executes its StartRouting function on a thread inside GatewayRouterController:

_signal.ContinueRouting = true;
while ( _signal.ContinueRouting )
   //If discontinue signal was given don't sleep
   if ( _signal.ContinueRouting )

As you can see, StartRouting does not terminate until it is signaled to do so. The class GatewayRouterSignal housed inside the GateRouterController and shared with the other classes is used to signal whether the Windows service must terminate or Routing must cease because it is outside of the service window.

The GatewayRouterControl is the Windows service. The Windows service code calls the Start and Stop functions on GatewayRouterControl to start and stop the service. As stated previously, GatewayRouterControl runs the GatewayRouterExecution on a separate thread. The following snippet of code executes the GatewayRouterExecution class on the thread:

_threadExec = new Thread(new ThreadStart(_routerExec.StartRouting));
_routingActive = true;

For more information on multithreading, check out following articles: “Multithreading in .NET Applications,” “Multithreading in .NET Applications, Part 2,” and “Multithreading in .NET Applications, Part 3“. For more information on constructing a Windows service, read “Creating a Windows Service in .NET“.

Applying the Solution

Before applying the ideas in the solution described here, consider the following ideas:

  • The Windows service can be used to supplement an existing integration solution such as BizTalk. You may have a Web service with a response type that BizTalk can’t handle out of the box, or you may simply have an unreliable Web service you want to handle in a specialized way.
  • The solution is a prototype. In your implementation, you may want to build a more configurable service window class.
  • The solution does not reuse SQL Server connections efficiently. Reusing connections efficiently will increase application performance.

Mitigate Web Service Reliability Problems

Web services can be unreliable. A Web service problem can exist on the client side, server side, or the Internet itself. You can mitigate Web service reliability problems by using an asynchronous messaging approach implemented inside a Windows service.

Download the Code

Download the code that accompanies this article.

About the Author

Jeffrey Juday is a software developer with Crowe Chizek in South Bend, Indiana. He has been developing software with Microsoft tools for more than 12 years in a variety of industries. Jeff currently builds solutions using BizTalk 2004, ASP.NET, SharePoint, and SQL Server 2000. You can reach Jeff at jjuday@crowechizek.com.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories