Tuesday, August 7, 2012

web service reliable messaging with sandesha

http://wso2.org/library/3429

However, specifications do not provide a reliable programming interface like JMS (Java Messaging Service). It specifies just a wire format for SOAP messages intended to be sent reliably. Read this article to find out how Sandesha2/C implements reliable messaging. Damitha Kumarage explains.

Introduction

Axis2/C is a Web services engine that is gaining popularity as a robust, feature rich Web services engine and is implemented in C. Sandesha2/C provides reliability for SOAP messages sent using Axis2/C by implementing the WS-Reliable Messaging specification. It plugs into Axis2/C as a standard module with two handler implementations within it, fitting into the Axis2/C in/out handler chains as specified by the module configuration. They provide implementation for RMSource and RMDestination specified in the specification. This implementation support both RM 1.0 and 1.1 specifications. It is interoperable with Microsoft .NET and Sandesha2/Java implementations.

Table of Contents

Reliability provided by Sandesha2/C

Underlying transport for sending SOAP messages could be any valid transport supported by the SOAP engine. It could be http, https, smtp, xmpp etc. We can't always expect the underlying transport to be reliable. Infact, http - the most widely used transport for SOAP is inherently unreliable. Also, we can't always expect that SOAP messages we send goes from a client to a service node. There could be many intermediaries between which the message hops, before it reaches it's final destination. We cannot predict whether the transport between any two intermediaries is reliable or not.
There are several aspects to reliability when transmitting SOAP messages. First, the sender of messages need to know whether he intends to know if the sent messages are actually received by the recipient. In that case, he needs to be acknowledged by the receiver. If the sender is not acknowledged within a predefined time frame then the sender should be able to resend the message until he receives an acknowledgment. The application environment that's sending out the message could be unreliable due to several reasons. The network could be broken, the server could be shutdown etc etc. This level of reliability is required from the specification and is provided by Sandesha2/C.
Second, there may exist the need for delivery assurance that the application message hits the target service exactly once. Although this is not required by the specification, it could be provided by a SOAP engine and Sandesha2/C do that for Axis2/C.
Thirdly, there may also exist the need for assurance that the messages are fed into the target service in the order they were intended to by the sender. Again, this is not required by the specification but the server could provide for it. This is in the TODO task list for Sandesha2/C.
Forth, suppose that the server shuts down before a sequence is completed. If the SOAP engine's reliability implementation provides a permanent storage mechanism to store the information related to the sequence(specifically at RMDestination), the sequence could be revoked when the server come back up. This level of reliability is not mandated by the reliable messaging specification. But Sandesha2/C has gone a step forward and implements this.
Finally, again, although not mandated by the specification, transaction support integration is deemed as necessary for certain business requirements. Sandesha2/C has no plans to support this yet.

Let's do it with Sandesha2/C

Before installing Sandesha2/C, you need Axis2/C installed and configured in your system. For further information on installing and configuring Axis2/C see here. After installing Axis2/C make sure that AXIS2C_HOME environment variable is set pointing to the Axis2/C installation folder(repository). You can download Sandesha2/C from here. After downloading do
./configure --prefix=${AXIS2C_HOME} --enable-static=no
--with-axis2=${AXIS2C_HOME}/include/axis2-1.3.0
make
make install
This will install Sandesha2/C into Axis2/C repository. After installing you will find following in AXIS2C_HOME repository.
$AXIS2C_HOME/modules/sandesha2
$AXIS2C_HOME/services/RMSampleService
$AXIS2C_HOME/lib/libsandesha2_client.so
$AXIS2C_HOME/bin/samples/sandesha2
For Windows operating system the instructions for installing is as follows:
  1. Unzip the source zip file and go into the extracted folder's build\win32 subfolder.
  2. Edit the configure.in with your binary locations.
  3. To set necessary environment variables on your cmd.exe run vcvars32.bat file.
  4. Run
    nmake dist
    command. This will build the Sandesha2/C binary and samples to a directory \build\sandesha2
  5. Now copy \build\sandesha2\Sandesha2 directory to your <AXIS2C_HOME>\modules directory
  6. Copy \build\sandesha2\bin\samples\RMSampleService to <AXIS2C_HOME>\services directory
Additionally, both on Linux and Windows platforms, you need to make sure that you add the RMPhase to the flows in axis2.xml in your repository directory pointed to by AXIS2C_HOME; environment varible. To do this add the following entry into inflow, outflow INfaultflow and Outfaultflow.
<phase name="RMPhase"/>
For more information on installing Sandesha2/C see Sandesha2/C documentation.
Note: If you download WSF/C then you need not worry downloading and installing separate packages for Axis2/C and Sandesha2/C and then integrating them. WSF/C is an integrated Web services platform which provides the user many Web services specific facilities in one package.
RMSampleService is an Axis2/C service engaged with Sandesha2/C for demonstration purposes. Engaging Sandesha2/C to a service is done by adding following line to services.xml.
<module ref="sandesha2"/>
If there is a need to engage Sandesha2/C to every service in the repository, you need to put this entry into Axis2/C main configuration file(axis2.xml).
There are two Reliable Messaging specifications released so far from W3C. They are WS-Reliable messaging version 1.0 and version 1.1. Sandesha2/C is designed to support both of these versions.
When sending SOAP messages, there are basically four message exchange patterns(MEP) possible. In-Only, In-Out, Out-Only, Out-In. These falls into two broader categories namely a request-response(two way) pattern, and a one-way pattern, which a communication protocol wishing to establish a communication channel is required to support. Currently, Sandesha2/C supports only SOAP over HTTP transport protocol. Usually, a service client using Axis2/C client API can send messages in several ways. He can use one of the following AXIS2/C client API functions to send messages:
axis2_svc_client_fire_and_forget()
axis2_svc_client_send_robust()
axis2_svc_client_send_receive()
axis2_svc_client_send_receive_non_blocking().
The first two falls into one-way pattern and the last two to two-way pattern. The difference between the first and second, is that in the second pattern, if the server triggers a SOAP fault this function would report an error back to the caller.
The request-response messages could be further categorized into synchronous and asynchronous. In synchronous mode the sender is blocked for a response from the server, whereas in the asynchronous mode the user is not. The third function above is synchronous and the fourth asynchronous.
Keeping those things about Axis2/C service client API in mind, let's now turn into sending messages reliably using Sandesha2/C. For an existing client which is not reliable, adding reliability is simple. You need to make sure addressing is enabled by:
axis2_svc_client_engage_module(svc_client, env,
AXIS2_MODULE_ADDRESSING);
and you need to add a line to engage Sandesha2/C to the client by.
axis2_svc_client_engage_module(svc_client, env, "sandesha2");
Today, SOAP over HTTP protocol is dominant for sending/receiving SOAP messages. However, doing two-way messaging using SOAP over HTTP posesses interesting issues. We don't have a contactable URI in some situations, like when sitting behind a firewall. In that case, there is a replay model implemented for Sandesha2/C, that could be used to do two-way messaging which uses the HTTP back channel to send messages from the server.
Now, let's go into detail with each of these.

One way

Once we engage a service and a client with Sandesha2/C as described above, the client and server exchanges messages reliably. While we proceed further, we will get clarified of certain elements pertaining to reliable messaging. Sequence is an element embedded into messages to make it identify as belonging to a certain sequence of messages. It has a SequenceID element to uniquely identify the sequence. RMSource and RMDestination are the words defined by RM Specification for sequence client and server. Here, sequence client means the one who initiated the sequence. RMSource and RMDestination should not be interchanged for the application client/requester and server/service. In two way reliable messaging, for the response sequence RMSource actually resides in the application server side and RMDestination actually resides in the application client side.

Once the message is sent by the client application, it is intercepted by the Sandesha2/C out handler that sits in the RMPhase of the outflow. It would temporarily hold this application message until registering a sequence with the server. Registering a sequence means sending a RM specific message called CreateSequence to the server with an AcksTo element and receiving from server a CreateSequenceResponse message which contain a SequenceID. AcksTo element contains an endpoint URL to which the acknowledgment messages must be sent from server. Thereafter all the application messages sent from client should contain this sequence id to mark that the message belongs to an established sequence between client and server until the client specifically terminate the sequence. In addition, each application message belonging to a sequence should have a MessageNumber element to mark the order of the message within the sequence. There could be any number of application messages associated with a sequence. Once the client receive the CreateSequenceResponse message it can send the temporarily held application message marked with the sequence id. Server could send an acknowledgment for this message to the specified URL in AcksTo element. In HTTP if the AcksTo URL is anonymous as it happen in most cases then the acknowledgment messages is sent in the HTTP back channel.
It is not required to send an acknowledgment for each application message from the server. Server can send one acknowledgment message containing an AcknowledgementRange element. AcknowledgementRange element contain the message numbers for all the messages so far received by the server. However a client could specifically request an acknowledgment request element in the sending message which should be promptly responded with an acknowledgment by the server.
When the client know that it has sent all the application messages intended for the server it can inform the server so by sending an application TerminateSequence message. In the RM 1.1 this will be responded by a TerminateSequenceResponse message.
It should be noted that all the strong typed words in the above paragraphs belongs to the WSRM namespace defined by the specification. You can define to which Reliable messaging version(1.0 or 1.1) this namespace should belong to by adding following code to the client application
property = axutil_property_create_with_args(env, 3, 0, 0,
SANDESHA2_SPEC_VERSION_1_0);
if(property)
{
    axis2_options_set_property(options, env,
    SANDESHA2_CLIENT_RM_SPEC_VERSION, property);
}
So far I have explained the all good scenario where nothing goes wrong between RM source and RM destination. What happens if network is broken and your second message in the sequence is not received by the destination?. Well the sever does not acknowledge for the second message you would say. yes that's correct. Then what will RM source do when it does not receive acknowledgment for the second message?. It will simply resend the application message number 2. But for how many times?. If the connection is broken indefinitely what happen?. In this case the client will resend the application message for a predefined number of times. The number of resends in such cases are determined by the RM Policy. Also the delay between sends is determined by the RetransmissionInterval by the Policy. Policy related xml configuration in the server or client repository should be edited before deployment to change the default values. Also there is a policy parameter called InactivityTimeout in Policy which is used to determine sequence timeout.

Two way dual channel

Two way messaging is basically understood as two one-way scenarios described above. One from client to server and other from server to client. All the request application messages from client to server belong to the sequence initiated by the client. All the response application messages from server to client belongs to the sequence initiated by the server. It should be understood that in the client there is both RMSource and RMDestination and so in the server side.

Two way single channel

Adding reliablity to a set of related application messages should not be a burden to the original sender or a receiver. If we increase RM specific messages such as CreateSequence, CreateSequenceResponse, Acknowledgement messages etc it would greatly reduce network efficiency. So if we reduce such RM specific messages to a minimum it would be a great way of providing reliability for the applications. One such mechanism is SequenceOffer element you can incorporate into your CreateSequence message. This element containa a RMSource generated sequence id, which would be offered to the RMDestination for acceptance. If the destination accept this by responding with an Accept element included in its CreateSequeceResponse message, then it does not need to specially send a CreateSequence message from server to client because response sequence id is already established by accepting the sequence id offered from the source.
This feature opens way for an application who has only single http channel to communicate in request/response pattern. For example, when we are behind a firewall and need to do two way messaging with our server reliably. Of course if there is no reliability, we can use the http back channel to send response messages synchronously. When reliability is on, we can still use the back channel to send response messages and acknowledgments in the http back channel. But how the server send us a CreateSequence message to establish a sequence to send response messages from server?\ We don't have a contactable URL behind our firewall to do that. You have the answer in sequence offer concept described above, because we can use SequenceOffer element in our CreateSequence message sent from client and avoid a CreateSequence message from server.
There is another method which could be used to do reliable messaging in a two way single channel using MakeConnection specification. In this method once the sequence is established Sandesha2/C starts a new thread for sending a new message called MakeConnection. This message body contains nothing more than an identifier element containing the sequence id offered for response sequence. HTTP back channel for this message provides a channel for response messages from server. For example, all application response messages from server and a terminate message from server are communicated through this back channel. The frequency of sending the MakeConnection message is determined by the PollingWaitTime Policy paramter.

Enhanced Reliability

Although not mandated by the specification Sandesha2/C provides a persistant storage mechanism to store sequence information in an sqlite embedded database. Because of this even in a server crash and recovery scenario the on going sequences can continue because sequence information are stored in a database. Sandesha2/C also provides 'exactly once' feature by dropping duplicate messages received by the destination.

Future

As explained earlier on, reducing the number of RM-specific messages greatly improves the network performance, when reliable messaging is engaged. As a future direction, it is planned to support AckRequested element, using which, we can configure to get Acknowledgement messages only when requested by the client.
Additionally, server could be configured to send acknowledgment messages only for missing messages. It does so by sending a Nack element to the sender that contains missing message numbers. This is intended as a future enhancement for Sandesha2/C. Also, it is planned to support Policy integration and security integration in to Sandesha2/C. The message ordering will also be supported by future versions.
More, there is plans to incorporate a sequence message monitoring mechanism tool into Sandesha2/C, so that one could easily track sequence messages from a database.

Summary

Sandesha2/C is the reliable messaging implementation for Axis2/C Web services engine. It could be easily integrated into your existing application written using Axis2/C to provide reliability with minimum effort. Sandesha2/C currently supports HTTP transport and has future plans to support other transports (supported by Axis2/C). It supports both one-way and two-way message exchange patterns. In addition, it provides a mechanisms to do two-way messaging using a single http channel between a client and a server both for RM 1.0 and RM 1.1. Sandesha2/C also features a persistant storage mechanism to support server shutdowns during a sequence progress.

No comments:

Post a Comment