典型的Web Service结构.docx
《典型的Web Service结构.docx》由会员分享,可在线阅读,更多相关《典型的Web Service结构.docx(13页珍藏版)》请在冰豆网上搜索。
典型的WebService结构
典型的WebService结构
(可乐 2001年11月01日18:
35)
典型的WebService结构。
不管你的Webservice是用什么工具,什么语言写出来的,只要你用SOAP协议通过HTTP来调用它,总体结构都应如下图所示。
通常,你用你自己喜欢的语言(如VB6或者VB.NET)来构建你的Webservice,然后用SOAPToolkit或者.NET的内建支持来把它暴露给Web客户。
于是,任何语言,任何平台上的客户都可以阅读其WSDL文档,以调用这个Webservice。
客户根据WSDL描述文档,会生成一个SOAP请求消息。
Webservice都是放在Web服务器(如IIS)后面的,客户生成的SOAP请求会被嵌入在一个HTTPPOST请求中,发送到Web服务器来。
Web服务器再把这些请求转发给Webservice请求处理器。
对VB6程序来说,Webservice请求处理器是一个与SOAPToolkit组件协同工作的ASP页面或ISAPIextension。
而对VB.NET程序来说,Webservice请求处理器则是一个.NETFramework自带的ISAPIextension。
请求处理器的作用在于,解析收到的SOAP请求,调用Webservice,然后再生成相应的SOAP应答。
Web服务器得到SOAP应答后,会再通过HTTP应答的方式把它送回到客户端。
典型的Webservice结构,点击小图放大
远程过程调用(RPC)与消息传递
Webservice本身实际是在实现应用程序间的通信。
我们现在有两种应用程序通信的方法:
RPC(远程过程调用)和消息传递。
使用RPC的时候,客户端的概念是调用服务器上的远程过程,通常方式为实例化一个远程对象并调用其方法和属性。
RPC强调的是远程对象和它的界面,即属性、方法和调用时的参数。
DCOM和.NET远程访问都是RPC的例子。
消息传递一般是在耦合度更低的系统中。
消息传递的概念是,客户端向服务器发送消息,然后等待服务器的回应。
消息传递系统强调的是消息的发送和回应,而不是远程对象的界面。
由于是基于消息的系统,客户端和服务器之间的耦合度比RPC方法更低。
RPC系统试图达到一种位置上的透明性:
服务器暴露出远程对象的接口,而客户端就好像在使用本地使用的这些对象的接口一样,这样就隐藏了底层的信息,客户端也就根本不需要知道对象是在哪台机器上。
例如,你在VB6中通过DCOM调用一个远程对象,你的代码看起来就与调用本地对象一样。
而消息传递则不同,它强调传递的东西是什么,但不管消息传递过去后干什么。
客户不需要知道服务器是怎么实现的,以及消息是怎么被处理的。
我们已经说过,你可以建立一个消息服务器,根据收到的消息来调用对象。
这是通过消息传递方式有效的实现了RPC。
如果客户仍然以消息的思维方式来进行操作,那么你可以把它叫做消息传递。
但如果客户以远程对象的思维方式来进行操作,那么你就应该把它叫做RPC。
如果你想实现一个基于XML的消息传递系统,大量的工作将集中在处理XML请求和应答消息上。
虽然VB6和VB.NET中,帮助你建立WebService的工具已经做了许多对XML消息进行处理的工作,但毕竟所有的数据都是用XML的形式收发的,许多情况下你还是需要对消息进行一些自己的处理。
深入理解XML和XMLSchema对于有效地实现XML消息系统是至关重要的。
建立WebService
我知道你现在已经很心急的想要写点代码,看看Webservice到底是什么样的了。
那么我们现在就介绍怎样用VB6和VB.NET实际做出一个Webservice来。
本节的目的只是向你展示一下这些工具的功能,而不是深入地讲解Webservice的工作原理。
本书后面的章节会向你慢慢说明Webservice以及MicrosoftSOAPToolkit和.NET等工具的内部原理的。
使用SOAPToolkit
Microsoft的SOAPToolkitV2帮助你把COM组件变成Webservice。
这套工具分为三大主要部分:
SoapClient是一个用于调用Webservice的COM组件;SoapServer是一个处理SOAP请求和返回SOAP应答的组件;还有一个WSDL向导,它可以把你的typelibrary转换成WSDL文档,以暴露给Webservice的客户。
假设你有一个COM组件,暴露出一个GetTemperature方法:
PublicFunctionGetTemperature(ByValzipcodeAsString,_
ByValcelsiusAsBoolean)AsSingle
要把这个组件变成一个Webservice,你可以使用WSDL向导。
给出你要转换的组件后,向导会要你选择你想暴露出的方法,指出生成的Webservice所在的URL(如http:
//localhost/Temperature/),以及你希望用ASP还是ISAPI做你的请求处理器(如图1-2)。
然后向导还会问你生成的WSDL和ASP文件应该放在那个目录下。
使用SOAPToolkit向导来转换COM组件,点击小图放大
现在该调用这个Webservice了。
方法是在VB或其他任何可以使用COM的语言里调用SoapClient组件。
下面这段代码演示了怎样调用Webservice中的GetTemperature方法:
DimsoapAsMSSOAPLib.SoapClient
Setsoap=NewMSSOAPLib.SoapClient
soap.mssoapinit_
"http:
//localhost/Temperature/Temperature.wsdl"
MsgBox("气温是:
"&_
soap.GetTemperature("20171",False))
首先调用mssoapinit,把WSDL文档的URL传给SoapClient。
WSDL文档的URL就是你在WSDL向导中给出的URL加上〈Service名字.wsdl〉。
一旦初始化完成,SoapClient就得到了Webservice的所有方法,你就可以直接调用这些方法了。
典型的WebService结构
(可乐 2001年11月01日18:
35)
典型的WebService结构。
不管你的Webservice是用什么工具,什么语言写出来的,只要你用SOAP协议通过HTTP来调用它,总体结构都应如下图所示。
通常,你用你自己喜欢的语言(如VB6或者VB.NET)来构建你的Webservice,然后用SOAPToolkit或者.NET的内建支持来把它暴露给Web客户。
于是,任何语言,任何平台上的客户都可以阅读其WSDL文档,以调用这个Webservice。
客户根据WSDL描述文档,会生成一个SOAP请求消息。
Webservice都是放在Web服务器(如IIS)后面的,客户生成的SOAP请求会被嵌入在一个HTTPPOST请求中,发送到Web服务器来。
Web服务器再把这些请求转发给Webservice请求处理器。
对VB6程序来说,Webservice请求处理器是一个与SOAPToolkit组件协同工作的ASP页面或ISAPIextension。
而对VB.NET程序来说,Webservice请求处理器则是一个.NETFramework自带的ISAPIextension。
请求处理器的作用在于,解析收到的SOAP请求,调用Webservice,然后再生成相应的SOAP应答。
Web服务器得到SOAP应答后,会再通过HTTP应答的方式把它送回到客户端。
典型的Webservice结构,点击小图放大
远程过程调用(RPC)与消息传递
Webservice本身实际是在实现应用程序间的通信。
我们现在有两种应用程序通信的方法:
RPC(远程过程调用)和消息传递。
使用RPC的时候,客户端的概念是调用服务器上的远程过程,通常方式为实例化一个远程对象并调用其方法和属性。
RPC强调的是远程对象和它的界面,即属性、方法和调用时的参数。
DCOM和.NET远程访问都是RPC的例子。
消息传递一般是在耦合度更低的系统中。
消息传递的概念是,客户端向服务器发送消息,然后等待服务器的回应。
消息传递系统强调的是消息的发送和回应,而不是远程对象的界面。
由于是基于消息的系统,客户端和服务器之间的耦合度比RPC方法更低。
RPC系统试图达到一种位置上的透明性:
服务器暴露出远程对象的接口,而客户端就好像在使用本地使用的这些对象的接口一样,这样就隐藏了底层的信息,客户端也就根本不需要知道对象是在哪台机器上。
例如,你在VB6中通过DCOM调用一个远程对象,你的代码看起来就与调用本地对象一样。
而消息传递则不同,它强调传递的东西是什么,但不管消息传递过去后干什么。
客户不需要知道服务器是怎么实现的,以及消息是怎么被处理的。
我们已经说过,你可以建立一个消息服务器,根据收到的消息来调用对象。
这是通过消息传递方式有效的实现了RPC。
如果客户仍然以消息的思维方式来进行操作,那么你可以把它叫做消息传递。
但如果客户以远程对象的思维方式来进行操作,那么你就应该把它叫做RPC。
如果你想实现一个基于XML的消息传递系统,大量的工作将集中在处理XML请求和应答消息上。
虽然VB6和VB.NET中,帮助你建立WebService的工具已经做了许多对XML消息进行处理的工作,但毕竟所有的数据都是用XML的形式收发的,许多情况下你还是需要对消息进行一些自己的处理。
深入理解XML和XMLSchema对于有效地实现XML消息系统是至关重要的。
建立WebService
我知道你现在已经很心急的想要写点代码,看看Webservice到底是什么样的了。
那么我们现在就介绍怎样用VB6和VB.NET实际做出一个Webservice来。
本节的目的只是向你展示一下这些工具的功能,而不是深入地讲解Webservice的工作原理。
本书后面的章节会向你慢慢说明Webservice以及MicrosoftSOAPToolkit和.NET等工具的内部原理的。
使用SOAPToolkit
Microsoft的SOAPToolkitV2帮助你把COM组件变成Webservice。
这套工具分为三大主要部分:
SoapClient是一个用于调用Webservice的COM组件;SoapServer是一个处理SOAP请求和返回SOAP应答的组件;还有一个WSDL向导,它可以把你的typelibrary转换成WSDL文档,以暴露给Webservice的客户。
假设你有一个COM组件,暴露出一个GetTemperature方法:
PublicFunctionGetTemperature(ByValzipcodeAsString,_
ByValcelsiusAsBoolean)AsSingle
要把这个组件变成一个Webservice,你可以使用WSDL向导。
给出你要转换的组件后,向导会要你选择你想暴露出的方法,指出生成的Webservice所在的URL(如http:
//localhost/Temperature/),以及你希望用ASP还是ISAPI做你的请求处理器(如图1-2)。
然后向导还会问你生成的WSDL和ASP文件应该放在那个目录下。
使用SOAPToolkit向导来转换COM组件,点击小图放大
现在该调用这个Webservice了。
方法是在VB或其他任何可以使用COM的语言里调用SoapClient组件。
下面这段代码演示了怎样调用Webservice中的GetTemperature方法:
DimsoapAsMSSOAPLib.SoapClient
Setsoap=NewMSSOAPLib.SoapClient
soap.mssoapinit_
"http:
//localhost/Temperature/Temperature.wsdl"
MsgBox("气温是:
"&_
soap.GetTemperature("20171",False))
首先调用mssoapinit,把WSDL文档的URL传给SoapClient。
WSDL文档的URL就是你在WSDL向导中给出的URL加上〈Service名字.wsdl〉。
一旦初始化完成,SoapClient就得到了Webservice的所有方法,你就可以直接调用这些方法了。
WebServices开发体会和在项目中的教训
作者:
出处:
构客网, 责任编辑:
李春禹,
2007-11-1309:
53
如果有以上需求,我想大家应该都比较认同这种异构分布式解决方案:
客户端用C#.Net开发,通过WebServices调用服务器端Java组件。
服务器组件测试一次,起容器特慢,而且客户端调用也慢。
我想大家一定会问?
为什么你们项目中要用到WebServices,因为客户有如下需求:
1、客户要求项目用C/S架构,并且服务器端是IBM那一套:
WebSphereAppServer+DB2+AIX5.3+RS/6000。
2、最终用户上报数据,因为网络原因,譬如Modem上网,可以离线操作,等填写了几十张报表后,可以一次提交。
同时,在登录时,可以将服务端数据同步到本地Access或MSSQL数据库,这样提高客户端响应速度。
3、由于有些报表以后可能需要修改,或添加一些新报表,又不想重新开发,这样客户那边工作人员可以通过客户端自定义。
如果有以上需求,我想大家应该都比较认同这种异构分布式解决方案:
客户端用C#.Net开发,通过WebServices调用服务器端Java组件。
其实,上面的解决方案太过于理想,最后我们不得不面对残酷的现实:
三种客户端中的两种最后被迫改为B/S。
在项目中,我主要负责WebServices和服务器端组件开发中所遇到的种种问题,相当于技术支持吧,以及部分模块的开发。
以下是我们开发中遇到的实际问题,虽然最终都一一解决,但遇到了几个无法突破的瓶颈:
客户端不稳定,客户端响应迟缓,后期测试和维护困难巨大。
一、异构平台的WebServices兼容性
开发过程中,我们用Axis做WebServices引擎,Tomcat做容器。
因为我们只有IBM提供的RAD6.0的60天试用版。
该工具超级占内存,用内置的WebSphere开发测试极其缓慢,严重影响开发效率,经过我初期试用后,基本废弃了。
推荐项目组二三十开发人员用Lombozeclipse3.12开发,基本满意。
由于Axis是一个嵌入式引擎,所以可以将其打包到最终的WebSphereAppServer(WAS)上,也就是说,我们没有用到WAS提供的WebServices引擎,这引出了后面会谈到的一个问题:
WebServices安全性怎么部署?
用Axis时,Axis一直都有一个bug或是说缺陷,官方文档也详细注明,只是我们当时没有发现而走了很多弯路:
用Axis发布的WebServices给.net客户端调用时,必须用RPC风格,不能用WebServices标准的跨平台风格Document,而后者是Lombozaxis插件的默认方式。
也就是说,我们发布的WebServices总是莫名其妙的不好用。
我们用JBuilder2007自带的Axis插件发布,竟然非常顺利。
二、WebServices开发中服务器端组件问题
我们服务器端开发,是用Spring+Hibernate,在Spring的Service层上再封装一层,也就是façade模式了,该façade直接发布为WebServices,必须经过这个转换,一是因为性能,二是因为Hibernate的复杂Model对象,在wsdl描述后,被.net客户端识别有些问题,List、Map也会有问题,总之这些对象太复杂了,我们包装成简单的VO对象。
另外一个问题是,我们的service方法,如果直接给WebWork这样的框架在服务端用的的话,是不会出问题,当提供给.net客户端用时,就会出现lazyloading的错误,因为.net客户端不能接收Proxy对象,必须将数据全部load出来,但这时Hibernate的session已经关闭。
项目组很多人遇到这些问题,最后大家不约而同的全部用eager模式,导致了最后的恶果:
严重的的性能问题。
由于我不是leader,所以当时这个问题发现了,也没法要求别人,毕竟很大的一个团队。
切身体会:
一个团队,如果不熟悉Hibernate就随便上,技术风险非常大。
Hibernate带来的开发效率,是以团队成员掌握它为前提。
当然,性能问题不只是由Hibernate引起,WebServices本身的性能也非常严重:
XML的序列化和反序列化耗时,XML文件的膨胀导致的网络传输,HTTP的无状态导致网络IO性能。
切身体会:
如果系统必须用分布式,而不是追求所谓的SOA架构,WebServices应该是下下策,因为还有很多协议和方式可以选择:
IIOP、RMI、Hessian、burlap、RPC,另外,做系统集成还有Message方式。
WebServices开发中其它问题比较少,因为WebServices本身不用编程,只是部署的事情,开发工具和服务器会自动为我们做,我们只需要理解SOAP引擎的原理和使用就够了,真的遇到问题,可以通过Axis的TcpMonitor监视SOAP数据包。
开发过程中,.net客户端那边,VSStudio做得很智能,它会根据wsdl文件生成我们所要的一切,当然,wsdl文件的变化,会导致VSStudio重新生成所有的类和接口,也很耗时,并且容易出问题。
三、WebServices的安全问题
当时解决WebServices安全问题,花了我将近一个月的时间,主要是学习和处理如下四个问题:
XML和WebServices安全规范
WAS的WebServices引擎的安全部署
Axis和参考的Xfire引擎的WebServices安全
.net客户端WSE3.0的安全以及和WAS的通讯
最后这些问题基本上都解决了,不过还是没有用上,因为在我们已经开发的几种客户端和服务器端部署上很麻烦,还要测试,另外,客户也没法验收这个啊。
当然,我们还回避了一个严肃的问题:
我们的WebServices是发布在Axis引擎上,还没有移植到WAS的WebServices引擎,而发布在这个平台,必须有RAD这类开发工具支持,几乎没法手动做。
WAS引擎的WebServices安全配置异常复杂:
我们当时只配置了Authentication和Integration,没有做Encryption,但完全够用。
我当时用Sun的NetBean开发工具发布了一下WebSerivces,也是挺好用的,不过没有配置安全。
顺便说一下,Sun的webServices引擎jwsdp2.0设计有点类似于EJB容器,很不好用,移植性特差。
我们当时用Axis引擎是1.3版本,而该版并不支持标准的OASIS的WS-Security,只有到2.0版才开始,而且几乎都是手写配置文件。
WAS的WebServices安全配置,对照IBM的红皮书,不是很难,但很复杂,安全相关的xml代码都好几百行,好几个文件。
配置过程中,和.net客户端通讯时遇到一个问题,怎么也不能互通,但.net和.net客户端可以互通,Java和Java客户端也可以互通,最后我通过拦截soap包,找到了解决办法:
必须手动更改http:
//docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3后的v3,IBM工具生成的是v1,这是标准不兼容引起的,因为当时RAD是04年底,而微软的WSE3.0比较新。
后来发现这篇文章有相似的经历:
在处理WebServices安全过程中,我通过emule和IBM网站下载了上10本这方面的书籍,我觉得以下资料对我帮助最大:
Axis的若干文档:
Reference、developers-guide、architecture-guide等,非常详细
IBM的红皮书:
《WebSphereVersion6WebServicesHandbookDevelopmentandDeployment.pdf》、《WebSphereApplicationServerV6SecurityHandbook.pdf》,它专门讲述了WebServices安全的原理和具体配置,非常深入浅出。
《SecuringWebServiceswithWS-Security》:
这本书很理论化,但我认为非常好,虽然Amazon排行不高。
WSE3.0的MSDN文档。
四、开发过程中的的沟通问题
这应该不是一个技术问题,而是一个软件开发方法学的问题,但对整个软件开发过程影响极大。
我们面对的现实:
.net客户端开发人员不懂服务器端Java,服务器端Java开发人员不懂.net。
除了技术壁垒外,还有业务衔接性的问题,因为我们不是纵向分模块开发,而横向开发的前提是我们服务器端开发人员很熟悉业务,知道客户端需要的接口,但实际上,业务主要由客户端推动。
所以,两端的开发人员都遇到很大的沟通壁垒。
从技术的角度表达就是:
客户端开发人员需要的接口,服务器端开发人员不清楚;服务器端开发人员也不知道怎么把握粒度。
譬如,有个updateUser方法,但更新用户信息时,可能需要更新很多信息:
用户信息、用户角色、用户所属组….。
loadUser时也有同样的按需加载问题。
当然,从技术角度,开发WebSerivces有Bottom-up和Top-down两种开发模式。
我们选择了前者,也是最常见的方式,也许用后者更适合我们的项目:
从定义的wsdl文件开始,客户端和服务器端开发都遵循它。
但问题是:
我们怎么确定wsdl,也就是我们所要求的接口,因为我们自己对业务都不是很熟。
五、客户端和服务端开发测试方法
我们当时做得很笨,也最直接:
等服务器端组件发布完毕后,通知客户端开发人员,然后客户端开发人员通过VSStudio提供的WebServices生成工具,根据Axis发布的wsdl文件,生成所需的.net对象,然后像本地调用一样使用。
但问题是:
wsdl随时都在变,这意味着客户端生成的组件总在变化,经常出现编译错误。
客户端开发过程中遇到的问题,一会是客户端自己,一会是服务器端组件:
我要的方法包含的信息不够啊。
服务器组件测试一次,起容器特慢,而且客户端调用也慢。
我们的测试,最后走入了一个怎样的泥潭:
譬如测试一张报表,都是在客户端手工填写,然后观察服务器端日志和响应。
有人会问,用LoadRunner或FunctionTester这类自动测试工具不就ok了吗?
我都用过,它们对WebUI确实好用,后者对Swing客户端也好用,但对.net客户端,像是不太现实。
另外,De