|
|
||
Mike Grogan's BlogWeb Services and XML ArchivesWhen to Use WSIT Reliable MessagingPosted by mikeg on February 25, 2007 at 03:56 PM | Permalink | Comments (0)Reliable messaging is a feature of WSIT, which will be delivered through Glassfish V2. Here is a link to the Milestone 3 build of WSIT. The first thing to know is that an client application programmer does not get to choose whether to use Reliable Messaging. If a Web Service endpoint uses it, it advertises the fact in a WS-Policy Assertion its WSDL. A WSIT client invoking the endpoint will always use Reliable Messaging when the Policy assertion is present. There are a few client-side Reliable Messaging configuration settings, but they are fine-grained ones. The default values work fine in almost every case. This means that the only special attention a client application programmer needs to pay to Reliable Messaging is the mechanism for closing a connection described here. In most cases, a client programmer does not need to know that Reliable Messaging is being used. The developer of a WSIT endpoint only needs to choose whether to enable Reliable Messaging, and if it is enabled, must decide whether to enable the ordered delivery feature. The decisions are reflected in Policy assertions in the WSDL of the endpoint. These assertions can be edited using the NetBeans 5.5.1 IDE. To make the decisions, it is important to understand some of the benefits and disadvantages of Reliable Messaging. BenefitsLet's start with some benefits. Reliable Messaging allows the WSIT Session support to work, but that is the subject of another article. The benefits discussed here involve the delivery assurances that Reliable Messaging is designed to provide. At least once deliveryIf Reliable Messaging is enabled, the client runtime will resend any messages that are lost in the network. This saves the client application programmer the effort of doing this in application logic. Arguably, this is mainly a service to the client, but there might be business reasons for offering the service. At most once deliverySome distributed applications will not work correctly without this delivery assurance. Consider a banking application with a payTo() method. Suppose that this is a client program: BankService service = new BankService(); CheckingAccount account = service.getCheckingAccountPort(); Suppose that the request message for the call to payTo is received and processed, but the HTTP response is delayed and the connection times out. In this case, the request will be resent and the payee will get a lucky windfall if the endpoint does not prevent the resent request from being processed by the business logic. On the other hand, duplicate detection is not always as important. Consider the code: StockQuoteService service = new StockQuoteService(); StockQuotePort port = service.getStockQuotePort(); float price = port.getQuote(“SUNW”); If the request message for the call to getQuote is processed several times, it will have no obvious ill effects.
Ordered deliveryLet's add a deposit() method to the CheckingAccount interface. Consider the code: BankService service = new BankService(); CheckingAccount account = service.getCheckingAccountPort(); If the request messages for the invocations of the deposit and payTo methods are processed out-of-order, the check will bounce if the initial balance was less than $500.00. Since the messages might cross paths in the network, the application needs a way to ensure that they are processed in the order in which they were sent in order to work correctly. In contrast, the StockQuote service in the example above will not malfunction if request messages for two quotes are processed out-of-order. In summary, the cases where the Reliable Messaging delivery assurances are crucial to an endpoint application are ones where request messages to the endpoint have side-effects and different orderings or cardinalities of the messages leave the system in different (and possibly unpredictable) states. On the other hand, for stateless services where invoking the operations has no side-effects, the benefits of the delivery assurances are not as compelling. DisadvantagesThere are disadvantages to enabling Reliable Messaging. Otherwise, it would be reasonable to enable it even in cases where there is no clear benefit. PerformanceThis is the most frequently-mentioned disadvantage,but might not really matter that much to many users. The Reliable Messaging protocol sends its own messages and adds protocol headers to application messages, so both the number of messages and their sizes are increased if Reliable Messaging is enabled. This increases processing times and decreases the number of requests that can be processed by a given endpoint. InteroperabilityThis might be the main disadvantage. Not all vendors of Web Services stacks support Reliable Messaging. The implementations of vendors who do support it might not even interoperate well, because of the looseness of the WS-RM Specification. (The specification is being standardized and tightened by The OASIS WS-RX Technical Committee.) WSIT Reliable Messaging endpoints are designed to work with WSIT and WCF Reliable Messaging clients, but may not work as well with clients using other software stacks. Therefore, enabling Reliable Messaging for a WSIT endpoint might limit the number of clients that are able to consume the service. SummaryUsing Reliable Messaging has real benefits. Indeed, some Web Service applications will not work correctly without the delivery assurances it provides. Not every application benefits from it however, and there are costs. A WSIT developer should weigh the advantages against the disadvantages for each application before enabling the feature. Closing WSIT Reliable Messaging ConnectionsPosted by mikeg on January 24, 2007 at 12:37 PM | Permalink | Comments (1)Most Reliable Messaging implementations in Web Services stacks, including the ones in Sun's WSIT and Microsoft's WCF are designed to operate "under-the-hood" with little or no effort required from client or server application programmers. There is one case where it is sometimes important for a client application programmer to communicate with the Reliable Messaging system. A Reliable Messaging connection requires both a client and endpoint to maintain state related to the connection. There is no automatic way for the runtime components to know when a client has finished using the connection, so an API (which I'll describe shortly) is provided for the purpose. If the client programmer uses the API, it allows the client runtime to send a WS-RM TerminateSequence message to the endpoint, so both client and endpoint runtimes can do an orderly shutdown of the connection, and discard any resources associated with it. This is analogous to the usual database programming model, where Connection objects have close() methods that perform a similar function. The JAX-WS 2.1 interface with the close() method (it's only method) is com.sun.xml.ws.Closeable. Every instance of a JAX-WS 2.1 client, whether it is a Proxy or a Dispatch implements Closeable, so the code: ((Closeable)client).close();always works, although it sometimes will have no effect. Calling the method provides a way for WSIT components, such as Reliable Messaging and Secure Conversations to do clean-up activities related to the client instance. Sometimes calling close() can be avoided without harmful effects. Every RM endpoint has a timeout interval. While a client is "still around", it will occasionally send messages to the endpoint to prevent a timeout, but if the client "goes away", the timeout will be reached, and the endpoint will assume that the connection is "closed". There is another very important benefit to calling close, though. Consider the program:
public static void main(String[] args) {
PingService service = new PingService();
PingPortType port = service.getPingPort();
port.ping();
}
Suppose that when this program is run, the request message for port.ping() is lost in the network. The way that a Reliable Messaging client does its job is to periodically check which messages have been acknowledged by the endpoint and and resend the ones that have not been. In this case, however, the end of the program will be reached before this can happen!
This can be fixed by adding the call to close():
public static void main(String[] args) {
PingService service = new PingService();
PingPortType port = service.getPingPort();
port.ping();
((Closeable)port).close();
}
By default, the call to close() will not return until all messages have been acknowledged. This means that the end of the main() method will not be reached until the request has been resent as many times as necessary for it to be acknowledged.
It is possible to override this default behavior. WSIT has a client-side Reliable Messaging setting called CloseTimeout.
If non-zero, it is the interval (in milliseconds) that the client runtime will block waiting for a call to close() to
return. When the timeout is reached, close() will return and a SEVERE log message will be emitted announcing the likelihood that messages have been lost.
In summary. There is com.sun.xml.ws.Closeable interface with a close() method that is implemented by every JAX-WS 2.1 client.
There is usually some benefit to using it and in a few cases, it is crucial. It never hurts to call it, even if the client does not use Reliable Messaging, so to be safe, it is a good programming practice to always call it.
Reliable Messaging in WSIT Milestone 2Posted by mikeg on September 22, 2006 at 02:10 PM | Permalink | Comments (0)Other than the usual bug fixes and minor adjustments needed to adapt to changes between WCF versions, the new work for the milestone consists of implementing some configuration settings that may affect performance. First some background: The WS-RM spec defines a SOAP-based protocol used by middleware components that exchange messages called the sender and receiver. It defines a way for a sender of to ask the receiver which messages have arrived and a way for the receiver to answer. The specification says little about how to use the protocol. Of course, the main use is that it allows the sender to ensure that all messages have arrived by periodically asking the receiver which ones have been delivered and resending the ones that haven't. A few variables affect the efficiency and performance of a system that does this. Namely how often the sender asks the receiver to account for the received messages and how often the sender resends the un-accounted-for messages. Imagine a scenario where almost no messages are lost. "Correct" values for these variables depend very much on the frequency of lost messages and the length of time it takes to deliver a message. We are exposing these variables as configuration settings, so end-users will be able to adjust them. The configurations are client configurations, unlike the other RM configurations that only affect the endpoint. As of Milestone 2, the settings are not exposed in the Netbeans UI, but it is possible to try them by manually editing the configuration files. Each setting uses a proprietary PolicyAssertion. They are:
<sun:AckRequestInterval Milliseconds="1000"/>
By default, retries happen every 2000 ms. The Resend setting in the Policy assertion will be used if it is larger than 2000, unless the system detects an abnormal build-up of unacknowledged messages, in which it will revert to the default value. By default the client requests acknowledgements on every application message. If a positive value is specified for AckRequestInterval in the policy assertion, the system will always wait for that interval between requests for acknowledgements, unless the system detects an abnormal build-up of unacknowledged messages, in which case it will refert to the default behavior.
As of Milestone 2, the settings are not exposed in the Netbeans UI. However it is possible to experiment with the
settings by manually adding them to the PolicyAssertion for an endpoint's wsdl:binding. Obviously, this is a
temporary arrangement, since the settings ultimately need to be part of the client's configuration. However, at the
moment, a client will use these settings if it finds them in the WSDL for the endpoint it is communicating with.
WS-Reliable Messaging and Session Support (Part 2)Posted by mikeg on August 16, 2006 at 11:35 AM | Permalink | Comments (0)This is Part 2 in a series of articles on supporting sessions using WS-ReliableMessaging. In my talk at Java One, I showed a demo of a Web Service endpoint that needs Reliable Messaging to work properly. Like most endpoints that benefit from Reliable Messaging, this one maintains state between requests. In Part 1 of this series, Bhakti has written an article that describes the demo.
The endpoint in the demo uses Session Identifiers that happen to be implemented using Reliable Messaging. These Session Identifiers are exposed as an experimental feature in Tango. This is one way that the contents of SOAP Headers used by WS-* protocols can be used to generate Session Identifiers. Secure Conversation Tokens can also be used for this purpose. Microsoft uses both mechanisms in Microsoft's Windows Communication Foundation (WCF).
Like most demos, this one has problems that would prevent it from being used in real-life applications. Also, like most demos, there are ways to improve it by doing more work. In this article, I'll try to indicate some of the advantages and disadvantages of this approach to session management and compare the approach with one that is an established feature of JAX-WS.
This approach is the use of HttpSessions. This article in Rama's Blog illustrates the approach. Here are some comparisons of HttpSessions and Reliable Sessions
Transparency
The HttpSessions approach requires that client application programmers explicitly enable session support by setting the javax.xml.ws.session.maintain BindingProvider property to true. The Reliable Sessions approach is transparent to the client programmer.
Interoperability
The JAX-WS Specification requires that every JAX-WS implementation support HttpSessions. This means that in every implementation, an endpoint can be deployed so that it supports HttpSessions, and the session support will work correctly with JAX-WS clients whose session support has been enabled.
The Reliable Sessions approach requires that clients support implement the non-standard WS-RM specification and define RM Sequences so that all requests belonging to the same session belong to the same sequence. This will always be the case with a Tango or WCF client, but may not be the case with other Reliable Messaging implementations.
Protocol Independence
HttpSessions require the use of the HTTP Transport. Reliable Sessions do not. With most current Web Services, this is not a significant limitation. In the future, the increased use of other transports such as FastInfoset will make it more significant.
Security
Both approaches are subject to attacks that tamper with parts of Request messages on which Session Identifiers are based. For HttpSessions this entails tampering with HTTP headers. For Reliable Sessions it entails tampering with SOAP Headers. Both risks can be addressed using transport-level security. In cases where message-level security is required, HttpSessions are vulnerable. On the other hand, Reliable Sessions can offer some defense in these cases. In particular, in Tango or WCF, if a Reliable Messaging endpoint is configured to use Secure Conversations, the same Secure Conversation Token will be used to protect each request messaging belonging to a given sequence.
Resource Management
This is the biggest problem with the demo. The demo endpoint maintains state for each client, and does nothing to discard the state belonging to clients that are no longer using the endpoint. This means that the Hashtable that stores session state will grow uncontrollably. Of course, we could improve the program by recording the last time each key in the Hashtable is accessed, and periodically removing keys that have not been accessed lately, but that is inconvenient. It would be nice if there was another experimental feature in the infrastructure to help us manage session lifetimes.
This problem does not exist for the HttpSessions approach. This is because HTTP Sessions expire if they are not accessed within a specified interval.
| ||
|
|