引言
Web服務是計算世界的新寵,它有望解決我們的所有計算問題,包括平臺差異以及與舊系統間的互操作性等問題。幾乎每篇相關文章都提到Web服務可以在各種協議上工作,但它們卻只詳細討論了SOAP/HTTP。
HTTP較容易理解,所以最常被定義和實現,但顯然它并不是Web服務的唯一選擇。
本系列的文章將討論在Web服務托管于WebSphere®ApplicationServer的情況下,如何通過實現簡單郵件傳輸協議(SimpleMailTransferProtocol,SMTP)上的SOAP使Web服務可用。本文展示了一些支持不同的“服務質量”并利用現有基礎結構的不同方法。本文將不討論Web服務的創建,只討論為什么為Web服務的接口使用SMTP上的SOAP綁定而不用更常用的HTTP/HTPPS上的SOAP。
本系列假設您已經對SOAP和Web服務技術有了大致的了解,所以就不再向您提供比較熟悉的顯示“面向服務的體系結構(Service-OrientedArchitecture)”的三角圖。對HTTP和SMTP有一定程度的了解也會有所幫助,但卻不是必要的。
這一系列文章中的示例使用的是IBMWebSphereStudioApplicationDeveloper,它使用內置的WebSphereApplicationServer,但任何遵守J2EE的應用程序服務器(包括Tomcat)也應該可行。
為什么選用SMTP?
HTTP上的SOAP之所以如此常用,原因有以下幾個:
HTTP協議無處不在-它隨處可見。
HTTP協議與防火墻兼容性很好,它只使用一些大家熟悉的端口,而且防火墻幾乎總是配置為允許HTTP協議通過。
HTTP協議使用HTTPS的“安全套接字層(SecureSocketLayer)”進行加密,并使用各種證書類型進行認證,很容易保護。
這些原因中的一部分也適用于SMTP協議。電子郵件和Web瀏覽一樣普遍-我們許多人都有多個可供每天查對的電子郵件帳戶。SMTP使用的是一個大家都熟悉的端口,所以很容易設置允許它通過的防火墻,而幾乎每個防火墻都被配置為允許該協議通過。加密沒有這么普遍,但通過PGP或其他方式的數字簽名還是很容易設置的。
此外,SMTP協議是異步的。調用者可以通過電子郵件發送請求,而且如果目標服務器宕機了,那么為了確保該電子郵件的發送,任何中間服務器都將重發好幾次。另一方面,如果目標服務器在請求時不可用,那么HTTP協議也將失敗。
選用POP還是原始SMTP?
SMTP協議提供了兩種獲取電子郵件的方法:
實現一個SMTP服務器,自己實現對基礎協議的支持。
使用一個現有的“郵局”協議,使用這種協議時電子郵件存儲在一個服務器上,并可由某個進程在適當的時機接收。
毫無疑問,您對這兩種方法都很熟悉,因為您的電子郵件程序把這兩種方法都用上了。傳出的郵件被配置為使用一個SMTP服務器,直接把消息發送給理解該協議的服務器。收到的電子郵件通常是用一個郵局協議-郵局協議(PostOfficeProtocol,POP)或因特網消息訪問協議(InternetMessageAclearcase/" target="_blank" >ccessProtocol,IMAP)-處理的,在您連接到因特網上檢索到這封電子郵件之前,它會留在您的ISP的服務器上。
SMTP協議或者郵局協議都可以用作Web服務分派器接口,接收請求并將它們發送給目標Web服務。我們將分別展示兩者的實現,但首先我們來討論一下它們各自的優缺點。為簡單起見,我們選擇POP作為我們的中間服務器協議,因為它比IMAP協議更常見也更簡單。
此外還有其他SOAP/SMTP實現,比如ApacheSOAP就是其中一個。然而,這種方法是先獲得一個傳入的SMTP請求,然后調用一個servlet接收HTTP協議上的請求,并將該請求傳遞給服務的實現。這一系列的文章將實現直接的SMTP,同時不會為將請求傳遞給目標服務而進行要求另一次網絡跳轉(即便是在同一臺機器上)的協議切換。
SMTP
SMTP協議的直接實現要求我們在標準SMTP端口(25)上安裝一個偵聽器,然后在調用者連接到該端口時執行該協議指定的交互。如果調用者不是通過中間機器而是直接連到我們的服務器上,那么Web服務客戶機就可以確定消息已被接收;否則它會收到一個通信錯誤,并可以立即對這次通信失敗采取相應的措施。然而,若服務器宕機,就無法再進行純異步的請求。
由于在多個服務器間分配電子郵件負載的機制得到了廣泛的理解,所以可伸縮性是很容易實現的。只要這多個服務器能處理請求,那么任何通過服務器多個實例之間的連接的適當路由都會成功,同時還提供工作負載管理和故障轉移。
由于SMTP實現將偵聽每個連接在它端口上的客戶機,所以任何發送至服務器的電子郵件都會被處理,而不管目標用戶(請想一下電子郵件中的To:域)是誰。因此,分派器例程能夠輕松地為各個用戶路由請求。
POP
POP協議直到服務器上的電子郵件被請求時才釋放它們??蛻魴C程序必須用顯式方法將它們刪除。您的電子郵件程序或許被配置為檢索后刪除電子郵件,但根據該協議這只是對服務器的一個單獨請求。分派器將周期性地輪詢POP服務器來檢索每封電子郵件,向目標Web服務發送請求,然后在這些請求被處理后將它們刪除。由于沒有一個直接的機制來告訴調用者電子郵件已被接收或已經發生了通信故障,因此這個過程是純異步的。
對于純SMTP實現來說,可伸縮性的實現更為復雜,因為必須在分派器服務器之間做一些協調工作以避免一個請求的多服務情況。
POP協議要求一個明確的用戶標識和密碼來連接和檢索電子郵件。如果您想為許多不同的用戶標識處理請求,就需要向POP服務器輪詢多個用戶標識。若服務器不僅要處理Web服務請求,還要處理為客戶機提供的響應消息,或者要根據目標用戶標識做出不同的路由決定,這么做就顯得尤為重要。
設計時的注意事項
在實現這樣一個框架時總是有許多注意事項。首先,盡量使前兩種實現(POP和原始SMTP)有更多的共性很重要。在多個地方做類似的事情是個不好的習慣。其次,您應當盡量靈活,允許部署多個能對請求起作用的對象,并在將請求傳送到實際的Web服務實現前盡可能做一下認證或其他一些檢查工作。靈活性的另一方面是使擴展—比如為另一個協議(例如IMAP)添加支持—容易進行。
您還要盡量多利用其他實現。為此,這一系列文章將實現在Java應用程序服務器的Web容器內運行的代碼。首先,您在支持HTTPS協議的同時最好也支持SMTP協議,因此,將兩種實現放到同一個運行時內是有意義的。使用應用程序服務器也使伸縮、配置、部署和運行時支持變得更加容易,因為您可以利用現有的基礎設施而不必自己新創建什么東西。
這種利用一部分是使用JavaMail以便能與SMTP順利交互。JavaMail是J2EE的一部分,所以它將自動被包含在任何遵守J2EE的應用程序服務器中。
由于對任何代碼而言,確保無錯誤才是關鍵,所以設計時可測性很重要,包括實現幾個JUnit類來支持類的自動測試。
您可能還想讓分派器盡可能快地處理請求,不要等一個請求處理完后才去處理另一個請求,這樣就要為每個請求啟動一個新線程。還是為了簡單起見,您可以只創建一個新線程,而不必使用一個ThreadPool來使開銷達到最少,就象在一個業界水平的實現中一樣。
兩個SOAP供應商的故事
有趣的是,對于一個SOAP供應商來說有多種選擇,并且它們都是Apache項目的一部分!
最常見的是ApacheSOAP,它提供一個servlet(RPCRouter)來接收傳入的SOAP/HTTP請求,如果需要的話對它們進行解碼,然后將它們傳遞給目標Java對象。這是最初的實現,但不幸的是它受到了一個主要問題的困擾:由于它使用DOM來處理XML,所以速度比較慢。處理SOAP中使用的XML可能是最慢的,而且可能是Web服務請求中最集中的處理部分。由于這個和其他幾個原因,已經發起了另一個倡導,并且這個倡導已經成了Apache項目Axis的一部分。它對SOAP消息使用SAX解析,這就為XML提供了一個簡單而又更加快捷的接口。Axis項目的工作正在進行中,即將發行代碼的beta測試版。
這個項目使用Axis是因為它速度更快。從理論上講,由于我們將對請求作異步處理,因此性能在這里并不那么重要。但這并不意味著我們就可以心安理得地慢下來,或者能接受DOM解析器的額外處理要求。我們只要解析XML就可以讓服務器敗下陣來,更不要說Web服務自身的處理要求了。
高級設計
高級設計使用的是啟動時加載(load-at-startup)servlet。這些servlet啟動使用原始SMTP綁定到端口25并等待傳入的電子郵件的守護線程,或者周期性地向POP服務器輪詢等待中的電子郵件的守護線程。圖1顯示了POPservlet、輪詢守護程序、處理器以及處理程序之間的一個對象交互圖:
圖1.對象交互圖
守護線程將根據它們正處理的協議做不同的工作。對于原始SMTP,該線程將獲得一個連接請求,然后將套接字傳遞給一個處理器(Processor)類來處理SMTP協議并檢索電子郵件。對于POP實現,該線程將周期性地輪詢POP服務器,并將各個電子郵件傳遞給特定于POP的處理器類。
我們的處理器類實現一個MailProcessor接口,并可以繼承一個AbstractProcessor類,AbstractProcessor包含我們所需的每個電子郵件協議都有的公共函數。這些類獲得電子郵件并將它們傳遞給一串處理程序(Handler)對象。
處理程序對象鏈可以被配置為執行日志記錄、將服務請求傳遞給SOAP引擎或處理響應等獨立的任務。我們的處理程序類可以繼承AbstractHandler,也包含公共函數。
結束語
本文介紹了許多關于我們的SOAP/SMTP實現的背景知識,包括SOAP/SMTP的優點、各種方法的優缺點和高級設計。下一篇文章將討論實際的實現,包括怎樣開始實現以及如何讓該實現在WebSphereStudioIDE中運行。
原文轉自:http://www.anti-gravitydesign.com