如果有以上需求,我想大家應該都比較認同這種異構分布式解決方案:客戶端用C# .Net開發,通過Web Services調用服務器端Java組件。服務器組件測試一次,起容器特慢,而且客戶端調用也慢。
我想大家一定會問?為什麼你們項目中要用到Web Services,因為客戶有如下需求:
1、客戶要求項目用C/S架構,並且服務器端是IBM那一套:WebSphere AppServer+DB2+AIX5.3+RS/6000。
2、最終用戶上報數據,因為網絡原因,譬如Modem上網,可以離線操作,等填寫了幾十張報表後,可以一次提交。同時,在登錄時,可以將服務端數據同步到本地Access或MSSQL數據庫,這樣提高客戶端響應速度。
3、由於有些報表以後可能需要修改,或添加一些新報表,又不想重新開發,這樣客戶那邊工作人員可以通過客戶端自定義。
如果有以上需求,我想大家應該都比較認同這種異構分布式解決方案:客戶端用C# .Net開發,通過Web Services調用服務器端Java組件。
其實,上面的解決方案太過於理想,最後我們不得不面對殘酷的現實:三種客戶端中的兩種最後被迫改為B/S。
在項目中,我主要負責Web Services和服務器端組件開發中所遇到的種種問題,相當於技術支持吧,以及部分模塊的開發。
以下是我們開發中遇到的實際問題,雖然最終都一一解決,但遇到了幾個無法突破的瓶頸:客戶端不穩定,客戶端響應遲緩,後期測試和維護困難巨大。
一、異構平台的Web Services兼容性
開發過程中,我們用Axis做Web Services引擎,Tomcat做容器。因為我們只有IBM提供的RAD6.0的60天試用版。該工具超級占內存,用內置的WebSphere開發測試極其緩慢,嚴重影響開發效率,經過我初期試用後,基本廢棄了。推薦項目組二三十開發人員用Lomboz eclipse3.12開發,基本滿意。
由於Axis是一個嵌入式引擎,所以可以將其打包到最終的WebSphere AppServer(WAS)上,也就是說,我們沒有用到WAS提供的Web Services引擎,這引出了後面會談到的一個問題:Web Services安全性怎麼部署?
用Axis時,Axis一直都有一個bug或是說缺陷,官方文檔也詳細注明,只是我們當時沒有發現而走了很多彎路:用Axis發布的Web Services給.net客戶端調用時,必須用RPC風格,不能用Web Services標准的跨平台風格Document,而後者是Lomboz axis插件的默認方式。也就是說,我們發布的Web Services總是莫名其妙的不好用。我們用JBuilder2007自帶的Axis插件發布,竟然非常順利。
二、Web Services開發中服務器端組件問題
我們服務器端開發,是用Spring+Hibernate,在Spring的Service層上再封裝一層,也就是façade模式了,該façade直接發布為Web Services,必須經過這個轉換,一是因為性能,二是因為Hibernate的復雜Model對象,在wsdl描述後,被.net客戶端識別有些問題,List、Map也會有問題,總之這些對象太復雜了,我們包裝成簡單的VO對象。
另外一個問題是,我們的service方法,如果直接給WebWork這樣的框架在服務端用的的話,是不會出問題,當提供給.net客戶端用時,就會出現lazy loading的錯誤,因為.net客戶端不能接收Proxy對象,必須將數據全部load出來,但這時Hibernate的session已經關閉。項目組很多人遇到這些問題,最後大家不約而同的全部用eager模式,導致了最後的惡果:嚴重的的性能問題。由於我不是leader,所以當時這個問題發現了,也沒法要求別人,畢竟很大的一個團隊。
切身體會:一個團隊,如果不熟悉Hibernate就隨便上,技術風險非常大。Hibernate帶來的開發效率,是以團隊成員掌握它為前提。
當然,性能問題不只是由Hibernate引起,Web Services本身的性能也非常嚴重:XML的序列化和反序列化耗時,XML文件的膨脹導致的網絡傳輸,HTTP的無狀態導致網絡IO性能。切身體會:如果系統必須用分布式,而不是追求所謂的SOA架構,Web Services應該是下下策,因為還有很多協議和方式可以選擇:IIOP、RMI、Hessian、burlap、RPC,另外,做系統集成還有Message方式。
Web Services開發中其它問題比較少,因為Web Services本身不用編程,只是部署的事情,開發工具和服務器會自動為我們做,我們只需要理解SOAP引擎的原理和使用就夠了,真的遇到問題,可以通過Axis的TcpMonitor監視SOAP數據包。
開發過程中,.net客戶端那邊,VSStudio做得很智能,它會根據wsdl文件生成我們所要的一切,當然,wsdl文件的變化,會導致VSStudio重新生成所有的類和接口,也很耗時,並且容易出問題。
三、Web Services的安全問題
當時解決Web Services安全問題,花了我將近一個月的時間,主要是學習和處理如下四個問題:
XML和Web Services安全規范
WAS的 Web Services引擎的安全部署
Axis和參考的Xfire引擎的Web Services安全
.net客戶端WSE3.0的安全以及和WAS的通訊
最後這些問題基本上都解決了,不過還是沒有用上,因為在我們已經開發的幾種客戶端和服務器端部署上很麻煩,還要測試,另外,客戶也沒法驗收這個啊。
當然,我們還回避了一個嚴肅的問題:我們的Web Services是發布在Axis引擎上,還沒有移植到WAS的Web Services引擎,而發布在這個平台,必須有RAD這類開發工具支持,幾乎沒法手動做。WAS引擎的Web Services安全配置異常復雜:我們當時只配置了Authentication和Integration,沒有做Encryption,但完全夠用。我當時用Sun的NetBean開發工具發布了一下Web Serivces,也是挺好用的,不過沒有配置安全。順便說一下,Sun的web Services引擎jwsdp2.0設計有點類似於EJB容器,很不好用,移植性特差。
我們當時用Axis引擎是1.3版本,而該版並不支持標准的OASIS的WS-Security,只有到2.0版才開始,而且幾乎都是手寫配置文件。
WAS的Web Services安全配置,對照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比較新。後來發現這篇文章有相似的經歷:http://pluralsight.com/blogs/kirillg/archive/2005/04/13/7315.aspx
在處理Web Services安全過程中,我通過emule和IBM網站下載了上10本這方面的書籍,我覺得以下資料對我幫助最大:
Axis的若干文檔:Reference、developers-guide、architecture-guide等,非常詳細
IBM的紅皮書:《WebSphere Version 6 Web Services Handbook Development and Deployment.pdf》、《WebSphere Application Server V6 Security Handbook.pdf》,它專門講述了Web Services安全的原理和具體配置,非常深入淺出。
《Securing Web Services with WS-Security》:這本書很理論化,但我認為非常好,雖然Amazon排行不高。
WSE3.0的MSDN文檔。
四、開發過程中的的溝通問題
這應該不是一個技術問題,而是一個軟件開發方法學的問題,但對整個軟件開發過程影響極大。
我們面對的現實:.net客戶端開發人員不懂服務器端Java,服務器端Java開發人員不懂.net。
除了技術壁壘外,還有業務銜接性的問題,因為我們不是縱向分模塊開發,而橫向開發的前提是我們服務器端開發人員很熟悉業務,知道客戶端需要的接口,但實際上,業務主要由客戶端推動。所以,兩端的開發人員都遇到很大的溝通壁壘。
從技術的角度表達就是:客戶端開發人員需要的接口,服務器端開發人員不清楚;服務器端開發人員也不知道怎麼把握粒度。譬如,有個updateUser方法,但更新用戶信息時,可能需要更新很多信息:用戶信息、用戶角色、用戶所屬組….。loadUser時也有同樣的按需加載問題。
當然,從技術角度,開發Web Serivces有Bottom-up和Top-down兩種開發模式。我們選擇了前者,也是最常見的方式,也許用後者更適合我們的項目:從定義的wsdl文件開始,客戶端和服務器端開發都遵循它。但問題是:我們怎麼確定wsdl,也就是我們所要求的接口,因為我們自己對業務都不是很熟。
五、客戶端和服務端開發測試方法
我們當時做得很笨,也最直接:等服務器端組件發布完畢後,通知客戶端開發人員,然後客戶端開發人員通過VSStudio提供的Web Services生成工具,根據Axis發布的wsdl文件,生成所需的.net對象,然後像本地調用一樣使用。
但問題是:
wsdl隨時都在變,這意味著客戶端生成的組件總在變化,經常出現編譯錯誤。
客戶端開發過程中遇到的問題,一會是客戶端自己,一會是服務器端組件:我要的方法包含的信息不夠啊。
服務器組件測試一次,起容器特慢,而且客戶端調用也慢。
我們的測試,最後走入了一個怎樣的泥潭:譬如測試一張報表,都是在客戶端手工填寫,然後觀察服務器端日志和響應。有人會問,用LoadRunner或Function Tester這類自動測試工具不就ok了嗎?我都用過,它們對Web UI確實好用,後者對Swing客戶端也好用,但對.net客戶端,像是不太現實。
另外,Debug非常困難,因為它要求兩端開發人員必須在一起密切配合。
我自己認為的解決方案,但未必真的好用:
服務器端Service方法必須寫單元測試TestCase,可能代碼量非常大,測試好後方發布為Web Services。
同時,服務器端提供同一套接口的Mock實現,供客戶端開發測試,解決並行開發的問題。
六、其它問題
當然,上面的幾點,具體到細節,我都省略了,總之問題非常非常多:技術問題、管理問題、方法和過程問題。
特別提的一點是,我們幾乎開發了兩套“業務層+持久化”解決方案,因為離線客戶端也用了NHibernate持久化,這樣導致開發測試工作量巨大,就說一點吧:兩邊同步是通過打包的sql語句,通過SOAP傳輸,但Access和DB2的sql有不兼容問題,如果要兼容,就會以犧牲性能和靈活性為代價。
另外,我們寫項目建議書時很被動,但也沒辦法,因為有好幾家公司競爭。對我們影響極大的幾個問題:
1、IBM的WAS比起WebLogic Server易用性差遠了,導致部署時極其耗時。而且還有一些bug,譬如連接池資源,當時不得不和IBM工程師咨詢。實際上,我們只用到強大的WAS的一個非常小的部分:Web容器。
2、我們沒有針對WAS的開發工具RAD。但說實話,那試用版的RAD也是一個字:慢,而且安裝時超級大,約4個G。而且和我們已經在用的版本控制工具VSS沒法集成。
3、項目的C/S架構不是很合理,就是原來客戶的B/S架構,也運行挺好的,而且用asp,跑在一個pc server上。我們一定程度上為了技術而技術。最後也達不到客戶需求:性能+穩定。
4、自定義報表最後沒有投入使用,只是一個半成品。本來自定義報表就很難,要是容易,一個軟件外行人員,就可以把表現層到持久化輕松搞定,那一般MIS開發人員不要失業了,MDA也沒那麼強。很多OA平台一直在解決這個問題,也沒有發現特別好用的。我們做技術調研期間試過MS的InfoPath和Adobe Designer,以及Excel Server,都不能滿足需求。
當然,這個子系統只是我們那個龐大系統的一個部分。上面也就算我做的一點點總結吧,也是教訓啊!不過,從個人角度考慮,學到的東西還是很多的。
這個子系統花去了我們將近200個人月,如果說那浪費的部分,估計至少是100個人月的工作量。是什麼導致?從我這篇文章只能窺其一角,因為整個系統涉及CMS、OA、BI、E-commerce、GIS、IM、MIS。我自己總結一下,有以下原因:
1、項目建議書空洞,不切實際:公司也很無奈,客戶也不成熟。
2、需求調研後的需求分析閉門造車:客戶的合同是分階段,我們上交需求說明書後付20%款,上交設計書後又付20%。全一個瀑布開發,雖然按RUP文檔寫。到半年後的實際開發時,發現很多需求都不合理。
3、整個過程都沒有和客戶溝通,到最後開發完畢才讓客戶看,那時客戶也懵了:這不是我要的產品啊。改呀,改呀,熬夜啊。
4、項目團隊整體技術實力薄弱,當時調來做Java開發的人員,只有少數幾個以前做Java,大多數是臨時學。想起那Hibernate使用,心寒啊。另外,WAS問題、AIX問題在產品環境下都出來了:系統不穩定、宕機。
5、整個開發階段流程沒有把握好,像項目規范、測試方法、日志、版本控制,這些後期都出現了,而且非常嚴重。就說那日志吧,最後出問題都不知道怎麼查,日志一遍混亂。
6、缺乏做大項目經驗,整個系統架構都比較松散,項目開始時很多都不知從何入手,也很倉促。
7、項目持續一年多,人都換了幾批了,工作交接很大問題。