使用Web服務也有半年多了,雖然時間不長,但還是遇到了不少難題,在這裡把我的一些經驗拿出來給大家共同分享。
剛開始做Web服務的時候還覺得很輕鬆,感覺就跟寫一般的組件沒什麼區別,而使用時跟引用普通的程式集一樣的簡單,這是因為Visual Studio替我們完成了許多不必要的繁瑣的工作。雖然如此,但是很容易造成我們的過分依賴,而忽略了Web服務發布和消費的內部工作機制。但隨著開發的深入,越來越多的問題擺到了我的面前,大概有以下幾個:
1. 動態url地址的配置
在消費Web服務時,最初都是直接引用靜態Url地址,後來發現當Web服務生產方的地址有所變化時,我的用戶端消費程式(此程式也可能是消費Web服務的Web應用程式服務端)必須要重新更新Web服務,這樣就會增大程式部署的難度。為了使消費程式更加靈活,於是我就在web.config中加入了一段appSettings的配置資訊,將需要修改的Url放入此段配置中,然後開啟在asp.net1.1工程中引用最初的靜態Web服務地址時自動產生的代理類檔案(通常是\Web References\’web服務名’\Reference.cs),將this.URL屬性修改為從設定檔中讀取剛配好的Url資訊,如:
web.config :<appSettings>
<add key="URL_AccountVerifyForWebservice" value="http://eai.ibss:9001/VerifyWebService//xxx.jws"/>
</appSettings>
Reference.cs :public class AccountVerifyForWebservice : System.Web.Services.Protocols.SoapHttpClientProtocol {
public AccountVerifyForWebservice() {
this.Url = ConfigurationSettings.AppSettings["URL_AccountVerifyForWebservice"];
}
.
}
這樣就降低了部署難度,因為在Web服務地址改變後,你不需要在開發環境中更新消費程式然後再重新部署到用戶端,而只需修改用戶端的web.config檔案內容就可以了,你甚至還可以自己配置一個xml檔案來列舉所有可能的url地址,然後在代理類中枚舉這些地址清單即可。
2. DNS解析問題
在一個項目中與Weblogic打交道,需要我的aspnet應用程式消費對方提供的web服務,雖然我很順利的完成了Web引用,即通過disco發現了Web服務,自動下載了wsdl檔案,並產生了代理類檔案,也正常通過了編譯,但是在運行時一旦開始invoke此web服務就會報錯,仔細檢查了代理類一切正常,很納悶搞不懂為什麼。後來有同事告訴我可能是DNS的原因,我這才知道Web服務的生產環境上建立了Server Load Balancer,而其提供的DNS伺服器負責將http://eai.ibss:9001/VerifyWebService/.../xxx .jws這樣的以網域名稱地址動態解析到所有提供Web服務的Server Load Balancer伺服器上,部署環境中的機器都可以通過此DNS訪問web服務。一開始,服務發布方提供給我的只是其中一台固定Web伺服器的靜態ip地址(如http://192.168.0.1:9001/VerifyWebService/.../xxx .jws),而wsdl文檔中描述的soap調用地址是網域名稱地址,引用時自動產生的代理類的Url屬性自然就是網域名稱地址了,而我的開發環境不能夠訪問DNS伺服器,也就不能解析網域名稱地址,所以在運行時會抱錯,因為soap資訊根本就沒有發送到正確的Web伺服器上去。這種開發,生產和部署環境的不同有時是非常令人頭痛的~~
後來通過採用第一個問題中介紹的設定檔的解決方案就很有效地解決了目前這個問題,開發調試時使用靜態地址,部署時更換為網域名稱地址即可。
3. Web服務和Web應用程式的分離
最好不要在同一台生產伺服器上同時部署web服務和消費此web服務的web應用程式,這樣會造成不必要的效能瓶頸。當用戶端請求一個web應用程式的某個頁面時,伺服器將佔用一個http串連,同時當該頁的產生或某個事件被觸發時需要同步調用一個web服務,那麼此時該伺服器將增加一個http串連的佔用,也就是說使用者請求一次頁面有可能會在伺服器上同時造成兩個http串連,若伺服器本身的http串連數為1000個的話那麼可能的實際使用者串連數只有500個。
4. 避免使用非string型資料
盡量避免在Web服務中使用非string型的資料作為Web方法的參數或傳回值,因為Java或者別的消費用戶端可能並不能夠正常解析int或arraylist這樣的資料類型,而string型幾乎是最通用的資料類型,至少與java能夠正常互動。盡量不要提供DataSet這樣的複雜資料類型,儘管網上已有許多解決方案,但我感覺都挺麻煩的,還不如將DataSet直接輸出到一個二維string型數組中。