随着Web服务的应用不断增多,对很多项目来说,只解决异构平台的分布式通信问题已经不够了。尽管互操作性是很多人考虑Web服务时的首要选择,但分布式系统还带来了很多难题使得互操作性不那么容易实现。在下面的文章中,我们将看看如何解决Web服务中的另一个分布式技术问题:可靠性。
可靠性一个关键概念,在涉及到金融相关数据时尤其如此。天气预报的Web服务代理信息与提供股票市场定单的Web服务是不能相提并论的。前者可以忍受网络失败并且接受新的请求而不产生大的影响,而如果后者没有必要的手段来处理这些问题就会产生严重的后果。基于此,在OASIS的赞助下出现了一个专门处理可靠性问题的Web服务说明书:WS-Reliability .
与其它Web服务说明书一样,WS-Reliability体现出可组合性的特点,它允许你按照需求混合匹配各种SOAP行为。通过这种方式,任何基于SOAP的应用都可以获得该可靠性层的好处,只需简单地添加SOAP头信息就能使用WS-Reliability中的任何规则。例如:
- 保证传送至少一次——发送的消息必须传送到接受端,要么给发送端一个发送失败的说明。
- 删除重复信息——最多发送一次,检测重复信息并在接受端删除。
- 保证消息顺序——消息按照顺序被发送
尽管WS-Reliability基于SOAP提供协议以某种方式传送有效负载等可靠数据,但还是要通过一个高层栈的翻译或处理来决定是否执行一个可靠通信。在WS-Reliability's中,高层栈是指能够进行转化的一种特殊环境,它可以是ESB或折like PHP/PEAR、 Java/Axis等Web服务框架。
这说明,就算用WS-Reliability实现的服务能够无缝地与其它服务交互,但唯一使用这些信息,还必须学习一个特殊的Web服务栈。有个例子,Apache Software Foundation创建的名为Sandesha 的WS-Reliability实现被加入了Axis框架中。而Axis框架是该基金会创建的一个Java Web服务栈。
现在,我们来看看Sandesha如何利用Axis框架创建可靠的Web服务。我们并不深入到细节,你可以查阅Sandesha的文档来看看它是如何加入到Axis架构中的。或者好好阅读Axis文档,如何你对它不熟悉的话。
我们的情景是一个Web服务客户端向一个股票报价系统发出一个可靠请求。表单1.1显示了我们的客户端如何使用Sandesha/Axis。
Listing 1.1
import org.apache.axis.client.Service; import org.apache.axis.client.Call; import org.apache.axis.encoding.XMLType; import org.apache.sandesha.Constants; import org.apache.sandesha.SandeshaContext; import javax.xml.namespace.QName; import javax.xml.rpc.ParameterMode; public class StockQuoteClient { private static String targetURL = "http://acmestockquote.com/axis/services/StockQuote"; public static Double stockQuote(String symbol) { Double priceObject = new Double(0.0); try { Service service = new Service(); Call call = (Call) service.createCall(); SandeshaContext ctx = new SandeshaContext(); ctx.initCall(call, targetURL,"urn:wsrm:stockQuotePrice",Constants.ClientProperties.IN_OUT); call.setOperationName(new QName("acmestockquote.com", "stockQuotePrice")); call.addParameter("Text", XMLType.XSD_STRING, ParameterMode.IN); call.addParameter("Seq", XMLType.XSD_STRING, ParameterMode.IN); call.setReturnType(org.apache.axis.encoding.XMLType.XSD_DOUBLE); ctx.setLastMessage(call); priceObject = (Double) call.invoke(new Object[]{"StockQuote", symbol}); ctx.endSequence(); } catch (Exception e) { e.printStackTrace(); } return priceObject; } public static void main(String[] args) { StockQuoteClient.stockQuote("SLB"); StockQuoteClient.stockQuote("BCA"); StockQuoteClient.stockQuote("SNY"); } } |
StockQuote方法包括我们的业务逻辑。首先,使用了Service和Call类,每个对象实例可以被基于Java Axis的Web服务客户端正常使用。在上面的例子中,它们都被保证可靠性的层SandeshaContext使用。
SandeshaContext用来维护在客户端和服务器端之间交互的状态。这就是为什么Call方法在ctx.initCall和ctx.endSequence之间被嵌套的原因。而它们正代表了Sandesha启动和结束一个可靠的过程。实际上,Call方法产生了一个不能被标准Web服务操作探测到的错误,例如被确保的传送或者重复的请求。Sandesha能够通过它的上下文来决定如何输出。
在表单中,你还能看到在ctx.initCall方法中有urn:wsrm:stockQuotePrice的命名空间。它代表了被加入到客户端请求中的额外SOAP头信息,它能被Web服务提供者识别用来完成可靠性过程。在Axis/Sandesha的例子中,尽管二者的结合提供了对构建具有翻译WS-Reliability客户端能力的服务提供者的支持,但它还具有本文没有提到的其它功能。不过,你应该注意到Axis/Sandesha框架已经与WS-Reliability进行了成功的测试,包括不同的Web服务栈上的客户端与服务器端,包括IBM、Microsoft 和Systinet。
至此,我们对Sandesha和WS-Reliability下一个结论。在解释了如何利用Web服务的可靠性特征后,你现在可以考虑实现其它的企业消息技术,例如至今可靠的分布式通信产品JMS (Java Messaging Service),并且用WS-Reliability提供同样的可靠性,但要继承平台无关的Web服务的所有优点。