題記:
本文是一篇有關SOA的文章的譯文,同時也是本人的畢業設計的文獻翻譯,完全出於學習和研究的目的,如果原作者對此有異議,請盡快與我聯系,我將在最短時間內撤掉該文章.翻譯盡可能的參照原文,有些細微的改動,文中的思想,我本人並不完全認同,比如有關面向對象的那段描述.翻譯不當之處,還請讀者諒解,畢竟水平有限:(
原文地址:http://www.XML.com/pub/a/ws/2003/09/30/soa.Html
譯文部分:
什麼是SOA
介紹
"事情可以變的盡可能的簡單,但不可能更加簡單"
--愛因斯坦
概述
愛因斯坦在數十年前做了上述的著名論斷,時至今日,這句話依然與大型軟件系統的構建息息相關.不幸的是,任何一個在IT業待了足夠長時間的人都能夠指出,有太多的軟件系統已經在愛因斯坦的這句話上失敗了.一些系統做的太簡單,以至於無法勝任其應當承擔的責任;而另一些則做的過於復雜,使的開發和維護的成本急劇上升,並且沒有注意到可能會出現的系統整合需求.看上去要達到"簡要"這個程度更像是一個不實際的夢想而已.我們到底錯在哪?
松耦合
問題其實就在我們身邊.當我們構建了越來越多的軟件系統後,出現了許多相似的場景和模式.很自然的,比起把它們全部除去,我們更希望能重復利用這些現有系統的功能.我們先給出一個名詞的定義.真實依賴:這是一種事件的狀態,它代表了一個系統依賴另一個系統提供的功能這種狀態.如果這個世界只存在真實依賴,愛因斯坦的試驗也許在多年以前已經實現的很好了.問題就在於,在真實依賴之間我們同樣創建了許多的虛假依賴.
如果你去海外出差,你知道你必須隨身帶著電源適配器,否則你的生活將一塌糊塗.真實依賴是,你需要電力,而虛假依賴是你的插頭必須插到當地的插座去.看看那些不同國家的各色的插頭,你會注意到,他們有些又小又緊湊,還有些則又大又粗.
這裡面給我們的教訓就是,虛假依賴是不可以移除的,但是我們可以削弱它.如果我們能夠理想的把系統間的依賴降到最低,那我們就已經達到了松耦合的目的,我們可以把那句明言重新加工一下:"虛假依賴應該降到最低而真實依賴是不可改變的."
SOA的定義和解釋
現在,我們可以給面向服務架構一個定義了.SOA是個旨在使相互作用的軟件業務達到松耦合效果的架構.服務是一個由服務提供者提供的,實現服務消費者的請求的業務單元.提供者和消費者都是軟件代理為了各自的利益而產生的角色.
這聽起來似乎有些太抽象了,但SOA實際上無所不在.讓我們來看個在我們生活中隨處可見的有關SOA的例子吧.拿CD做例子.如果你想播放CD,你會把CD插到一個CD播放器裡面來播放.CD播放器提供了播放CD的服務.令人高興的是,你可以更換不同的CD播放器.你可以用一個隨身的播放器或是你的昂貴的立體聲系統來播放同一張CD.他們都給您提供了播放CD的服務,但是服務質量是不同的.
SOA的思想與面向對象思想有著許多意味深長的差異.在面向對象編程中,數據和行為被強烈的建議綁定在一起.因此,在面向對象的設計中,每個CD應該伴隨它自己的播放器,並且不應該被分開.這聽起來有些奇怪,但這確實是我們構建許多軟件系統的方法.
服務的結果通常可以改變消費者的狀態同樣也可能改變服務提供商的狀態也可能都改變.在你用你的CD播放器聽完音樂後,你的心情發生了變化,從"沮喪"變成了"高興".如果你想要一個涉及到雙方狀態改變的例子,那麼在飯店吃飯將是個很好的例子.
我們想找人幫忙做某項工作通常是因為那個人是那個方向的專家.而消費一個服務通常要比我們自己干來的更便宜和高效.我們大部分的人都能意識到我們不可能成為每個領域的專家.這個道理同樣適用於構建軟件系統.我們稱之為"關注分離",這已經被認為是軟件工程的一條基本原理.
SOA如果來達到使交互的軟件代理松耦合的目的呢?它通過滿足以下兩條約束來實現:
1.參與的軟件代理的簡單並且普遍存在的接口的小集合.只有通用的語義會在這些接口裡編碼.這些接口對所有的提供者和消費者都是全局可用的.
2.接口間傳遞的消息必須是可描述的並通過擴展方式傳遞.沒有,或者只有極少量的系統行為被消息訂閱.樣式約束了消息的詞匯和結構.擴展的樣式允許新版的服務在舊有的服務存在的情況下被使用.
正如在上面的電源適配器的例子上所說的,接口非常的重要.如果接口不工作,那麼整個系統也將癱瘓.在分布式系統中,接口則是即昂貴又易於出錯的.接口需要指示系統的行為,而在不同的平台與語言之間要實現接口是非常困難的.遠程接口同樣也是在大部分的分布式系統中最慢的一種.與為每個應用程序都創建新的接口相比,為所有的應用程序創建一些可重用的接口則要有意義的多.
因為我們只擁有很少的一部分可用的通用接口,我們必須在消息中表示應用程序特定的語義.我們可以通過我們的接口發送任何消息,但是在我們宣稱某個架構是面向服務的之前,我們必須遵循一些規則.
首先,這個消息必須是可描述的,因為服務提供者有責任解決問題.這就好比你來到一個飯館,告訴侍者你要點的菜單,但是你不會手把手的告訴他們的廚師怎麼來做你要吃的魚.
第二,如果你的消息沒有按照一定的格式,結構來書寫,服務提供者將不能理解你的請求.限制了詞匯和結構的消息對於任何一次高效的交流都是必須的.消息受限的地方越多,則這個消息將越容易被理解.雖然這需要通過犧牲擴展性來達到目的.
第三,擴展性非常的重要.要理解這一點並不難.這個世界是個在不斷變化的世界,這個道理同樣存在於軟件系統所處的各個環境.這些變化要求軟件系統進行相應的變化,包括服務消費者,提供者,還有他們相互交流的消息.如果消息是不可擴展的,消費者和提供者將都受限於某個特定的服務版本.盡管擴展性如此的重要,不過在以往的情況,依然容易被忽略.最好的情況也只是,它(擴展性)被簡單的認為是種好的模式而不是基礎.約束和擴展性是一對深深的矛盾體.兩者你都需要,你提升了任何一方都將削弱另一方.最好能夠尋找到一個正確的平衡點.
第四,一個SOA必須擁有一個機制,它能使的消費者在其尋找到的一個服務的上下文環境下發現一個服務提供者.這個機制應當非常的可變,並且不是必須擁有一個中央注冊處.
額外的約束
在SOA中,有幾項額外的約束用於提供其可測性,性能,和可靠性.
無狀態服務
每個消費者發送給提供者的消息必須包含所有提供者處理該請求所需要的信息.這個約束使的提供者更加的可測,因為提供者不需要在請求之間保存信息.自從每個請求都被通用的對待後,這有效的形成了"服務的批量生產".同樣可以宣稱這個約束提高了可見度,因為任何一個監控軟件都可以監控單個的請求並指出其目的.由於不需要擔心中間狀態,因此從部分的失敗中恢復也是簡單的.這使的服務更加的可靠.
有狀態服務
有狀態的服務在許多場景下難於避免.其中一個便是在消費者和提供者間建立一個會話.會話是典型的為了性能而建立的.例如,為每個請求發送安全證書對消費者和提供者都是相當沉重的負擔.如果把證書替換成消費者和提供者之間的一種共享的標記,則會快上許多.另一個場景是給消費者提供服務.
有狀態的服務要求消費者和提供者都共享同一特定消費者的上下文,它可能被提供者和消費者間的交互的消息所包含或引用.這個約束的缺點是,它可能全面降低服務提供者的可測性,因為提供者可能需要為每個消費者記憶共享的上下文.它同樣還增多了服務提供者與消費者間的耦合關系,使的服務的篩選變的更加的困難.
冪數請求
被一個軟件代理接受到的重復請求與單個的請求擁有相同的效果.這個約束允許提供者和消費者通過簡單的進行"如果請求失敗則重復執行"來全面提高服務的可靠性.
源自SOA的WEB服務
每個人都大概的了解,什麼是"WEB服務",但是並沒有一個可被廣泛接受的定義.WEB服務的定義同時也被W3C WEB服務框架工作組激烈的討論.盡管定義一個WEB服務是如此的困難,但是大致說來滿足下列約束的WEB服務就是一個SOA:
1,接口必須基於互聯網協議,例如HTTP,FTP和SMTP
2,除非是二進制附件,消息必須是XML格式
有兩個最重要的WEB服務格式,分別是:SOAP的WEB服務和REST的WEB服務.