SOA中的服务接口设计最佳实践.docx

上传人:b****6 文档编号:3620171 上传时间:2022-11-24 格式:DOCX 页数:15 大小:80.16KB
下载 相关 举报
SOA中的服务接口设计最佳实践.docx_第1页
第1页 / 共15页
SOA中的服务接口设计最佳实践.docx_第2页
第2页 / 共15页
SOA中的服务接口设计最佳实践.docx_第3页
第3页 / 共15页
SOA中的服务接口设计最佳实践.docx_第4页
第4页 / 共15页
SOA中的服务接口设计最佳实践.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

SOA中的服务接口设计最佳实践.docx

《SOA中的服务接口设计最佳实践.docx》由会员分享,可在线阅读,更多相关《SOA中的服务接口设计最佳实践.docx(15页珍藏版)》请在冰豆网上搜索。

SOA中的服务接口设计最佳实践.docx

SOA中的服务接口设计最佳实践

SOA中的服务接口设计最佳实践,第2部分:

使用服务向服务使用者应用程序报告错误

级别:

中级

MikhailGenkin(genkin@),认证IT架构师,IBM 

2007年12月20日

在本文中,我们将了解如何在SOA环境中使用服务接口来报告服务错误。

面向服务的体系结构(Service-OrientedArchitecture,SOA)强调企业内不同系统间的松散耦合。

应用程序彼此间的通信只能通过设计良好的服务接口进行,并不会考虑彼此的实现。

服务接口结构在SOA中是最重要的。

设计糟糕的服务接口可能会对需要使用其的所有应用程序造成负面影响。

通过本文可了解设计良好的服务接口如何帮助加速项目计划的执行,从而提高您的SOA解决方案对业务需求的响应能力。

引言

本系列的第1部分重点讨论了服务接口设计的最佳实践,包括设计与开发方法、服务粒度、同步设计与异步设计的比较以及操作签名。

在本文中,将重点介绍相关最佳实践,以说明服务应该如何向服务使用者应用程序报告错误。

除了成功响应外,生产质量级的系统还必须能够处理各种错误情况。

服务向服务使用者应用程序报告错误的方式会影响服务接口的结构,从而也会影响服务使用者应用程序的构造方式。

用于报告错误的WSDL构造

第1部分讨论了描述服务接口的最佳方式就是使用Web服务描述语言(WebServicesDescriptionLanguage,WSDL)。

WSDL规范包括如下规定:

∙服务接口(端口类型)包含一系列操作。

∙每个操作可以为请求-响应型,也可以为单向操作。

∙每个请求-响应操作可以定义单个输入消息、单个响应消息和任意数量的错误消息。

∙单向操作不能定义响应消息或错误消息。

WSDL规范还进一步定义消息可以包括一个或多个部分。

每个部分的值可以为简单XSD类型,也可以为用户定义的复杂类型。

请参见参考资料,其中提供了指向WSDL规范的链接。

错误类型

服务需要报告的错误实际上可归入两类:

系统级别

表示属于服务实现的一部分的运行时软件组件、硬件和网络通信协议的错误。

这些错误代表不与所执行的业务逻辑或数据相关的错误。

例如,如果服务实现需要访问的RDBMS服务器崩溃,由于应用程序服务器无法找到该服务器的Java™DatabaseConnectivity(JDBC)连接,因此您的服务器无法处理请求消息,则将出现典型的系统级错误。

业务级别

由于服务违反业务逻辑或数据相关规则而引发的错误。

例如,如果请求消息表示请求预订旅程,而回程日期字段的日期早于出发日期,则服务实现将可能引发业务级别的错误。

最佳实践:

对于具有请求-响应操作的同步体系结构,请在操作签名中定义系统和业务错误。

应该使用不同的XSD类型描述系统错误和业务错误。

服务使用者应用程序通常需要以不同的方式响应系统级别和业务级别的错误。

对于系统级别的错误,服务使用者应用程序可能希望等待并使用原始数据再次尝试请求。

对于业务级别的错误,应用程序可能希望将消息发送回最终用户,要求对输入数据进行更正。

在请求-响应操作中使用WSDL错误

错误仅能与请求-响应操作一起使用。

图1显示了可以如何设计WSDL端口类型的结构,以向客户机应用程序返回业务级别和系统级别的错误。

此操作基于经常使用的StockQuote示例。

StockQuote服务包含单个StockQuote端口类型(接口)。

此端口类型包含名为getQuote()的操作。

此操作接收作为getQuoteRequest消息的一部分的输入消息。

结果作为getQuoteResponse消息的一部分返回。

图1.示例端口类型

getQuote()操作还定义了另外两个消息,用于向服务使用者应用程序返回错误。

∙getQuoteBusinessFault返回与不正确使用服务相关的错误,如服务使用者应用程序提供了未知或空的股票代码。

∙getQuoteSystemFault返回系统导致的错误,如数据连接问题等。

按照第1部分中所述的最佳实践,在独立的XSD文件中定义错误类型。

此XSD包含复杂类型,用于表示SystemError和BusinessError。

最佳实践:

错误消息应该包含单个WSDL部分。

此部分的值是复杂XSD类型,其中包含错误的完整描述。

上面图1中的示例端口类型显示了使用错误返回错误的请求-响应操作。

此操作的结构按照IBM®WebSphere®IntegrationDeveloper6.0或IBMRational®ApplicationDeveloper6.0及7.0中提供的WSDL编辑器中所示的方式显示。

清单1显示了XSD文件中定义的复杂类型的结构。

您可以下载示例代码,其中说明了复杂错误类型的定义方式。

BusinessErrorType和SystemErrorType均通过扩展公共基类型BaseErrorType派生而来。

BaseErrorType定义两个元素:

∙faultName将应用程序特定的错误名称提交给服务使用者应用程序。

例如,如果服务使用者应用程序为股票代码参数传入null或空字符串,返回给应用程序的错误名称可以为“Invalidsymbolformatfault”。

∙message提供较为深入的说明,并指示要进行的纠正措施。

例如,“Nulloremptysymbol.PleasepassavalidstocksymboltothegetQuoteoperation”。

faultName和message元素对可以由getQuote操作引发的任何错误类型都是通用的,因此定义为所有错误的基类型。

清单1.ErrorTypes.xsd摘录

type="string"minOccurs="1"maxOccurs="1">

type="string"minOccurs="0"maxOccurs="1">

BaseErrorType">

BusinessErrorCodeType"

minOccurs="1"maxOccurs="1">

BaseErrorType">

SystemErrorCodeType"

minOccurs="1"maxOccurs="1">

minOccurs="1"maxOccurs="1">

maxOccurs="unbounded">

SystemError和BusinessError类型都定义errorCode元素。

此元素包含一个字母数字代码,唯一地标识服务可以返回的每个错误类型。

服务将字母数字代码与描述错误的文本信息一起返回非常重要,因为客户机应用程序(服务使用者)可能会希望以编程方式检查此代码,并以不同的方式定向后续调用(根据错误代码所指示的错误类型)。

最佳实践:

错误消息应该包含错误代码,以允许服务使用者应用程序(客户机)以编程方式处理错误。

应该将错误代码作为WSDL服务定义不可或缺的部分发布,以便于服务使用者应用程序理解所报告的错误的含义。

清单2显示了用于将错误代码传递到服务使用者应用程序的简单类型的定义。

两个简单类型BusinessErrorCodeType和SystemErrorCodeType都通过限制(restriction)派生自xsd:

string类型。

限制中的枚举定义可以为业务级别错误和系统级别错误返回的错误代码。

XSD中嵌入的注释可为服务使用者(客户机)应用程序开发人员描述错误代码的含义。

清单2.定义

--Invalidsymbolstringformat-->

--Symbolnotfound-->

--Authenticationerror-->

--Databaseconnectionnotavailable-->

此示例将业务级别的错误和系统级别的错误归入不同的类型,以明确地对二者进行区分,而且可供服务使用者应用程序方便地以编程方式处理错误代码(如果必要)。

在很多情况下,只需定义单个简单类型,就足以包含所有描述业务级别和系统级别的错误语义的错误代码。

不过,将业务和系统错误代码分组到独立的编号段的做法(例如,业务级别的错误从00010到00100,而系统级别的错误从001000到010000)非常明智,可便于对这些代码进行编程处理。

对于即使在例外路径上性能也非常关键的情况,您可能会希望将错误代码字段设置为int或short类型,因为数字型字段比字符串字段处理起来更快。

最佳实践:

应该将系统和业务错误的数字值分组为不同的段(请参见下载),以便服务使用者应用程序代码以编程方式进行检查。

SystemErrorType类型包含可选元素,可用于捕获关于导致问题的错误的信息。

例如,StockQuote服务可能在尝试与后端数据库进行通信时捕获java.sql.SQLException。

为了对此进行响应,我们的服务将构造并引发SystemErrorType。

SytemErrorType应该包含原始异常的名称,还可以选择性地提供导致问题的java.sql.SQLException异常中的额外消息堆栈跟踪信息。

在大多数情况下,如果服务使用者和服务提供者应用程序属于相同的组织,服务开发人员可能会选择不向服务使用者应用程序报告原始错误。

这是一个非常好的做法,可促进问题确定和解决。

在操作响应中返回错误

使用WSDL错误的另一个方法是将错误信息作为常规响应消息的一部分返回。

应用程序开发人员趋向于采用此方法,特别在涉及到使用Web服务进行批处理时。

这种情况下的批处理应用到的操作的输入消息包含多个不同的输入,而响应消息可能包含多个不同的结果(每个均与某个输入对应)。

例如,StockQuote服务的输入消息可能包含多个股票代码,而响应消息也将包含多个结果。

此方法具有一系列优缺点。

(本系列的后续文章将更详细地讨论与批处理相关的问题。

在非错误响应中返回错误代码的主要好处在于,此方法允许服务使用者应用程序(客户机)按照与处理非错误响应相同的方式处理错误信息。

图2显示了如何采用此方式返回错误信息。

这样,客户机应用程序就可以获取Web服务返回的响应Java对象,并直接将其传递到表示层(通常为JavaServerPages),以向最终用户显示。

这就避免了创建用于将服务使用者应用程序的表示层与Web服务层分离的转换对象的过程中涉及到的额外编程工作。

图2.作为响应消息的一部分返回错误信息的单向操作与请求-响应操作

此方法的主要缺点有:

∙客户机应用程序必需访问资源,检查响应中提供的结果元素是否为空,分析并返回systemError和businessError值,并恰当地做出反应。

业务逻辑与大量的技术查询和条件语句混杂在一起。

使用WSBPEL编写的业务流程特别容易受到负面影响。

Web服务业务流程执行语言(WebServicesBusinessProcessExecutionLanguage,WSBPEL)提供了错误处理程序构造,能够通过图形构建程序工具将其从主要业务逻辑活动序列分离出来。

如果WSBPEL流必须持续对响应结构进行自检,并评估结果和错误字段的值,那么所得到的图形将很难提交给业务用户并向其进行说明。

∙服务使用者应用程序(客户机)代码的用户界面部分与服务接口紧密耦合。

以后对服务接口的更改可能导致有必要重新编写用户界面。

最佳实践:

对于不涉及批处理的请求-响应操作,请使用WSDL错误从服务接口将错误信息返回到服务使用者应用程序,而不要在响应消息和状态代码中返回错误信息。

∙服务使用者应用程序运行所在的应用程序服务器将不会注意到Web服务所导致的问题。

返回结果的所有响应看起来都像没有发生错误的调用,而且跟踪文件或system.out日志中将不会显示有关问题的信息,因此会对问题确定带来障碍。

由于存在这些缺点,因此从请求-响应操作返回错误和消息的最佳做法是依赖于WSDL错误构造,并使用前面描述的方法返回错误。

在异步拓扑中返回错误

WSDL规范(请参见参考资料)并不允许为单向操作定义错误。

不过,遵照异步模型构建的应用程序的确需要访问错误信息的功能。

可以采用以下三种方式之一设计异步调用的结构:

∙无响应的单向异步调用

发布-订阅交互就是此方式的一个示例。

当应用程序实现没有响应的单向异步调用时,由于WSDL规范不允许为所使用的单向操作定义错误,因此没有办法向服务使用者应用程序提供错误反馈。

服务使用者应用程序也对稍后获取响应没有兴趣,因此没有办法使用响应消息向客户机提供错误信息。

在此情况下,您必须非常细心地处理基础设施配置,以确保请求消息不会在发往预期目的地的过程中丢失。

最佳实践:

实现异步拓扑时,使用响应消息返回错误。

∙稍后发出响应请求的异步调用

涉及到执行两个请求-响应操作(虽然大部分处理工作都是由目标服务以异步方式执行)。

例如:

1.服务使用者应用程序调用submitStockQuoteRequest()操作。

此操作向服务使用者应用程序返回事务确认编号。

2.stockQuoteService实现执行股票值的查询操作。

3.服务使用者应用程序稍后调用getStockQuoteResponse()操作,并传入submitStockQuoteRequest()返回的事务编号。

此操作返回的响应操作包含股票值结果和错误信息(如果有)。

图3显示了在这种情况下应该如何设计操作签名的结构。

请求操作可能会导致系统错误。

这些错误仅仅传递与输入消息交互及异步处理初始化相关的错误信息。

用于检索响应消息的操作应该按照上面所述的常规请求-响应操作的方式引发系统和业务错误。

图3.StockQuoteAsynch端口类型的结构

∙使用回调返回请求的异步调用

服务使用者应用程序提供相关信息,以允许服务将响应消息发送回客户机(服务使用者)应用程序定义的接口。

如果在异步处理阶段发生业务错误,服务实现将在查询响应消息时引发业务错误。

最佳实践:

当使用请求-响应操作进行异步处理时,在请求操作上仅定义系统错误,而在用于检索响应消息的操作上同时定义系统级别和业务级别的错误。

处理客户机应用程序中的错误

清单3显示了一个示例,说明了客户机应用程序将如何处理StockQuote所引发的业务和系统错误。

JavaAPIforXML-basedRPC(JAX-RPC)和JavaAPIforXMLWebServices(JAX-WS)规范说明了WSDL和XSD所描述的类型如何转换为客户机所使用的Java对象。

由于我们定义了不同的复杂类型来表示这些错误,因此RationalApplicationDeveloperWeb服务工具会生成不同的JavaBean来表示它们。

这些Bean派生自JavaException类,可以在不同的catch块中进行处理。

最佳实践:

调用Web服务时,捕获所有已声明的错误,并在独立的catch块中处理系统和业务错误。

客户机应用程序调用Web服务时,必须处理生成的代理的方法签名中定义的异常。

除了这些异常外,客户机堆栈还可能会引发与序列化和通信相关的其他错误。

通常,除了处理代理方法签名中定义的异常外,最好也对基础java.lang.Throwable进行处理。

这可确保客户机应用程序代码足够强壮,能够处理客户机为了响应各种情况(如格式存在问题的响应消息——序列化类型错误)而引发的非预期异常。

清单3.请求-响应处理的客户端错误处理示例

publicclassSQFacade{

privateintretryCount=0;

privateStockQuoteProxysqProxy=newStockQuoteProxy();

publicStringgetQuote(Stringsymbol)throwsUIError

{

Stringresult=null;

UIErrorerror=newUIError();

try{

result=sqProxy.getQuote(symbol);

}catch(BusinessErrorTypee){

//Checkthecodeandreturnappropriateactiontouser

BusinessErrorCodeTypeerrorCode=e.getErrorCode();

if(errorCode!

=null)

{

if(errorCode.getValue().equals(BusinessErrorCodeType._SQ00010))

{

error.setMessage("Invalidinputformat!

");

error.setAction("Pleasere-enterthesymbolvaluecorrectly.");

}

elseif(errorCode.getValue().equals(BusinessErrorCodeType._SQ00020))

{

error.setMessage("Stocksymbolnotfound!

");

error.setAction("Pleaseenteradifferentstocksymbol.");

}

else//Justincase!

{

error.setMessage("Usererror!

");

error.setAction("Pleasecontactsiteadministrator.");

}

}

else//Justincase!

{

error.setMessage("Usererror!

");

error.setAction("Pleasecontactsiteadministrator.");

}

throwerror;

}

catch(SystemErrorTypee)

{

//Checkthecodeandreturnappropriateactiontouser

SystemErrorCodeTypeerrorCode=e.getErrorCode();

if(errorCode!

=null)

{

if(errorCode.getValue().equals(SystemErrorCodeType._SQ001001))

{

error.setMessage("Authenticationproblem!

");

error.setAction("Pleasepleasecontactthesiteadministrator.");

}

elseif(errorCode.getValue().equals(SystemErrorCodeType._SQ001002))

{

//Retry3timestoseeifdbconnectionproblemclearsup

if(retryCount<3)

{

retryCount++;

this.getQuote(symbol);

}

retryCount=0;

error.setMessage("Dataaccessproblems!

");

error.setAction("Pleasetryagainatalatertime.");

}

else//Justincase!

{

error.setMes

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1