不久前我看過一部電影<<幸福終點站(The Terminal)>>, Tom Hanks所飾演的主角被迫生活在一個機場,因為他是一個無國籍的人,他的國籍不被承認是因為就在他去美國的路上他的祖國解體了,他的國家不再存在了.當然,我想這隻是一個編劇為了抓住觀眾的心而想出的新情節,以為它只是一個喜劇而以.然而事實上,這部電影是以Merhan Karimi Nasseri的真實生活故事為背景的,因為法國的移民問題還有他不願回到他的祖國伊朗的原因,他在巴黎的戴高樂機場生活了將近二十年.本質上說這件事和面向服務沒有任何關係,但是這件事使我想起一個問題,那就是有人近期在一個研討會上提到的關於SOA的問題:服務需要保持差異性嗎?
在SOA的所有核心原則之中,大概最基礎的就是服務提供者和消費者之間的鬆散耦合關係.SOA的核心靈活性和重用優越性依賴於服務提供者和消費者在用於描述互動的服務合約條款架構內各自獨立運作的能力,並且,對於一個特定的SOA來說,至關重要的是不能為其能力和行為加入非必要的要求或限制,因為無論是服務提供者和消費者都可能隨時間而改變。
無差異性原則對於鬆散耦合的需求來說是十分必要的。畢竟,一個服務要通過訊息傳遞為軟體提供介面。不存在一種與對象執行個體類似的服務執行個體的表示方式;相反地,服務只是簡單的停在那裡,和他的每個訪問者通訊。更具體的講,既然SOA包括了獨立實體之間通過服務耦合進行的互操作,我們只需要在服務之間傳遞訊息和資料就可以了。這些松耦合的、異構的、複合的應用程式要求所有的服務必須是無差異性的,以保證他們不會將自己的系統或進程地資訊暴露給外部從而增加了系統的耦合度,那會導致可重用性和可用性的下降。
將不同服務組和在一起的原因是要實現商務流程,而這些流程必定是有差異性的,畢竟,一個進程的不同執行個體可能處在不同的狀態。於是如何利用無差異的服務實現有差異的事務邏輯就變成了十分重要的挑戰。如果實現方式不對將會失掉由無差異的服務帶來的松耦合的好處。
在SOA中維護差異性資訊
Wikipedia 是這樣定義“差異性”的:這樣的差異性保留了過去的資訊,如一個使用者記錄或購買事務,並且差異性反映了系統從起始到目前時間的所有變化過程。在這個“差異性”定義的基礎上,出現了許多關於另一個概念“計算”的定義:從一個狀態到另一個狀態的轉變以及他們之間轉換髮生的條件。對於一個進程來說,差異是十分重要的,因為如果沒有差異性,我們的系統將沒有任何曆史可供積累。實際上,我們開發的大部分系統,要麼是記憶差異,要麼對差異進行操作。進一步來說,各個公司都需要之前的狀態來從某種錯誤的更新狀態中恢複。最要緊的是沒有前一步的狀態記錄,我們做到任何的可靠交易,因為無法在發生問題的時候進行回退。
因此,既然差異性對於一個資訊系統如此之重要,那麼為什麼不把差異性的表示和維護功能包含在SOA中呢?回答這個問題的關鍵,在於充分瞭解差異性資訊在一個松耦合的系統中是需要被共用還是獨立在各個服務中。
鬆散的耦合是否意味著不需要差異性?
鬆散耦合使得SOA具有很高的效率。這就是說,SOA增加了靈活性,並使得一些互不干擾地各自啟動並執行服務能夠儘可能多被重用,所以,就不會在服務使用者的行為和能力上強加一些不必要的需求和限制。在這種情況下,特定服務活動的差異性概念就應該在服務內部保持而不應該暴露給使用服務的客戶,這將變得很有意義,因為這樣當差異性萬一需要發生變化的時候,就不需要讓所有的服務使用者來操作這種變化。更具體的來說,因為SOA包括了組成服務的實體之間的合作,所以就僅僅需要把訊息和資料從一個服務傳遞到下一個服務,這樣帶來的缺點則是所有的服務將需要儲存各自的狀態。
然而,即使在SOA的環境之中,為了獲得那些跨組織或者跨公司的長期啟動並執行進程資訊,仍然應該在每個獨立的服務實現之外保持差異性的值。而且,一些進程需要保留多個服務的現場,為了這些進程的性質的要求,同時也為了安全、管理等目的,一些差異性的表現也是必需的。
用沒有差異的服務保持有差異的系統
沒有差異性的web表現出同樣的問題,這些web必須儲存一些跨越多個web的session,而每個web都不會獨自儲存狀態。基本上有兩種方法可以在web上儲存差異:一種是在瀏覽器中儲存一個擁有多個互動資訊的cookie,另一種是在伺服器上以某種方式跟蹤差異,可以用網路的普通協議來交換儲存的session資訊的方式來實現這種跟蹤。
使用Cookie儲存差異只有在web上才適用,因為它們本身就是HTTP的結構,而HTTP是Web最基礎的協議,每個瀏覽器都支援它。但是,當涉及到服務的時候,需要考慮系統到系統的通訊,因為不可能所有的使用者都是瀏覽器,或者更一般來說,都支援某種特定的協議。這就使得只有訊息能夠在SOA環境下儲存差異性。
本質上,跨多服務的儲存差異性是有可能的,這種儲存可以通過對每個服務訊息打上某種持久的標記來實現。而這種標記將代表一種跨越多服務互動活動的持久狀態,表現良好的服務會把這種標記以混合的方式不加刪改地傳遞到其他的服務,這種傳遞會通過管理這些服務的協議來進行。通過這種方式,個體服務仍然是沒有差異性的,但是訊息能夠儲存那些特殊服務的組件所需要的差異性。
這種基於訊息的差異性儲存方法迴避了問題的本質,那就是到底要怎樣來管理服務元件代表的進程。傳統的BPM(業務處理管理)工具利用了代表所有運行進程的運行時組件引擎,而這些引擎儲存了差異性。這種方法的優點是它提供了對運行進程的可見度並儲存了相關服務的差異性。
然而,這種方法有一些嚴重的問題:第一,一個核心進程的運行環境僅僅能給服務可見的服務和服務元件提供差異性的儲存。一旦服務的請求超出了系統的邊界,進程工具將不再能夠控制進程。第二,進程的活力性依賴於進程工具的活力性——如果工具崩潰並丟失了資訊狀態,那麼就沒有方法來恢複進程執行個體。但是也許這還不是最嚴重的事情,因為核心進程的運行環境降低了鬆散耦合的性質會導致所有的服務提供者和使用者都必須通過進程服從核心工具的控制。
此外,這裡已經完成的是把BPM和面向服務的BPM分開,這種面向服務的BPM建立在差異管理的基礎之上。一種理解這種區別的方法是在練習時嘗試“去掉伺服器”。當一個核心BPM工具停止時,正在啟動並執行進程將會出現什麼情況?因為核心工具控制了所有的進程邏輯,包括差異性邏輯,因此停止工具其實就意味著所有進程的終止,這經常是不可恢複的。
解決這些問題就必須要用面向服務的方式儲存進程的差異性。也就是說,通過約定的服務提供差異管理,這些服務的目的就是為進程執行個體儲存差異性。本質上,這種方法把訊息當作事件來處理,差異儲存服務能夠對這些事件審計,記錄日誌,並在以後根據這些記錄分析決定給定的差異。這種方法認為差異性是運行系統潛在的缺點而不是運行進程環境應該儲存的一些必需資訊。這種事件驅動的、面向服務的方法跟蹤所有相關的事件,並且有一個單獨的服務集合來分析事件流並執行專門的過程,這些活動是基於進程的需求,政策以及服務的協議等。
現在,當進程管理的服務集合停止以後會發生什麼呢?因為服務提供者和使用者互動的訊息包含了持久地標識,這些標識代表了進程的差異性,所以進程的資訊將不會丟失。相反,發送到進程管理服務的訊息被放進一個隊列,等待服務恢複再處理。一旦服務被恢複,則可以繼續執行它沒有處理完的進程邏輯,因為隊列中的訊息能夠提供它需要的關於當前進程差異的所有資訊。
從一個設計師的角度來看,在面向服務的設計中考慮差異性是十分有必要的。服務除非它是差異性管理服務且在特別要求這樣做時一般自己不保留差異資訊。就算這樣做時,它們也管理那些暴露給差異性管理服務的進程。在任何情況下不會有一個服務管理自己的差異性資訊,因為一個服務消費者通常自己知道一個服務的內部狀態便於確定是否給服務發送訊息。如果那樣的話會破化SOA中鬆散關係和封裝原則。
有效率的公司設計師已經認識到,就如所有有關SOA的文章中所闡述的,好的設計隨協議而改變。也就是說,雖然差異性無關是一個獨立的服務通過鬆散串連獲得靈活性的必要條件,狀態無關也是商業程式為獲得商業目的而需要的條件,所以這種手段是一種平衡來用於它們在採用面向服務設計方法的共同需要。