日志對許多應用程序來說是都是一個重要的組成部分,至少存在兩種類型的日志: 一般信息的和 關鍵業務的。
一般信息日志主要用來跟蹤應用程序的步驟和操作。根據日志信息的用途,它對應用程序的操作有著不同的影響。例如,如果日志記錄只是用來進行統計分析,少數幾次失敗的日志操作將是可以接受的。然而,如果日志是用來審計,那么遺失日志記錄將是不可接受的,這就要用到第二種類型的日志:關鍵業務日志。
在這種情形下,根據業務的相關程度,日志的輸出將影響到系統的其它部分,換句話說,其它應用程序將讀取關鍵業務日志并應用到它們的商業邏輯中。這種類型的日志將像其它的一些業務操作一樣被謹慎處理。這類日志的一個例子就是金融系統的日志,那些記錄財務事務信息的日志可用來進行興趣統計、稅費計算或僅僅是用來滿足法律要求,如可跟蹤性。
不幸的是,在目前系統在,一些重要的日志消息,(可能是一般信息日志或關鍵業務日志),很少被認真處理。原因在與日志操作經常被當作一種輔助操作,日志資源被當作一種只寫的設備,只滿足快速和廉價即可。
基于日志的自身內在特性,Web 服務是實現日志的很好的選擇。因為對業務關鍵日志敏感的企業同樣會對一個企業范圍內所有應用程序都能夠使用的日志服務感興趣,并且Web服務還提供了日志記錄及其生命周期的集中管理能力。
在本文中,我們將提出一種企業范圍的日志 Web 服務架構,它重點解決分布式系統 2 個關鍵設計方面: 可靠性和容錯性和 事務語義支持的日志。
日志的容錯性和可靠性
在本節我們將基于 WS-Reliability 標準討論與日志有關的 Web 服務可靠性問題,并提出一個可靠的日志 Web 服務架構方案。
可靠日志的需求
在討論技術細節之前,我們首先定義可靠性以及日志 Web 服務需要實現的可靠性需求
從一個用戶的角度出發,可靠性經常是一種需求,下面兩段引文對什么是可靠性給出了很好的定義:
- 根據文獻 分布式系統-概念和設計(請參閱 參考資料),一個計算機系統的可靠性是對系統的行為偏離它最初的設計行為(即根據正確行為的定義)的可能性大小的度量,它包括在沒有任何個別的錯誤操作的前提下發生的系統中止。可通過設計系統來發現系統偏離(或錯誤)并從中恢復來提高系統可靠性。
- 可靠性的第二個定義源于文獻 分布式系統-原理和示例(請參閱 參考資料) ,它指系統在不發生故障的前提下連續運行。一個高可靠系統是指系統在無故障前提下一個相當長的時間周期內可以最大可能的持續不間斷工作。.
這兩個定義從根本上說明,你希望建立的日志 Web 服務是在一個相對較長的時間范圍內可以不間斷工作,且具有發現故障并從中恢復的能力。
日志需求記住上面的定義,則不難確定一個可靠日志 Web 服務的可靠性需求。下面的列表描述了一個可靠日志 Web 服務所必須實現的需求:
- 實現可靠的消息傳遞:未來的設計技術方案必須保證提交到日志 Web 服務日志消息能夠傳遞到服務器端且被處理。
- 除去重復消息:日志 Web 服務除了必須保證消息被提交外,還要確保即使一條消息被提交多次,在服務器端也只處理一次。
- 確保消息次序:協議和設計技術方案必須保證提交到 Web 服務的日志消息按照它們的發送時的次序在服務器端處理。
- 日志客戶端和 Web 服務容錯性:日志客戶端和 Web 服務需要能夠發現錯誤并能夠從錯誤中恢復。
這意味著,要實現一個可靠日志 Web 服務,未來的技術方案必須保證消息傳遞到服務器端并按照正確的順序處理一次(且僅處理一次)。另外,方案必須保證提交的日志信息必須是可持續化的,即使服務器或客戶端崩潰等特殊時刻。
高層架構
在詳細討論之前,我們還必須明確幾個定義。在本節,我們為日志 Web 服務提出了高層架構,研究架構體系內的組件,并定義整節中使用的通用術語。
圖 1 顯示了組成日志方案的高層組件,并定義了日志客戶端與 Web 服務進行交互的兩個場景。
圖 1: 日志場景
圖 1的上半部分顯示了最基本的場景。 這里,日志客戶端與日志 Web 服務直接進行交互。
圖 1 下半部分顯示如下場景: 日志客戶端并不直接與日志 Web 服務進行交互,日志信息被傳遞到一系列稱為跳轉的中間服務。不管是日志客戶端的直接通信組件還是日志 Web 服務來作為跳轉,都需要保持透明。
本文將不對跳轉進行單獨討論,但從架構的觀點來看,如果與日志客戶端交互,那么它就像一個日志 Web 服務,如果與日志 Web 服務交互,那么就是一個日志客戶端。
組件在上一節我們研究了主要組件-日志客戶端和日志 Web 服務。在本節我們將從架構的角度對日志 Web 服務進行詳細研究。
圖 2: 基本日志服務架構
圖 2 中的高層視圖并沒有給出太多的技術細節,只是用來說明組成日志 Web 服務的 2 個主要組件。
簡單地,日志 Web 服務從總體上可以分為 2 部分:
- 日志客戶端:組件封裝了一個可靠日志客戶端,應用程序通過提供的 API 可以使用它。組件可以從應用程序中接收日志信息并通過可靠的方式提交到日志服務器。在本文中這一組件通常被稱作 客戶端或 日志客戶端.
- 日志服務器:此組件是應用程序的核心部分,它為日志客戶端提供了一個進行可靠日志的 Web 服務。日志服務器接收日志信息并采用可靠的方式進行處理,在本文中這一組件通常被稱作 服務器或 日志服務器.
應用程序是 圖 2 中的第 3 個組件. 應用程序并不屬于日志 Web 服務,由于它使用 Web 服務,因此它在本文上下文中也很重要。
在整篇文章中,這一組件被稱為 商業應用程序.
WS-Reliability 標準
作為討論的基礎,我們對 WS-Reliability(請參閱 參考資料)進行概述,并討論了它的關鍵元素和機制。 然而,你會發現, WS-Reliability 標準很好地覆蓋了協議層上關于可靠性的問題,但并沒有涉及到應用層上的可靠性問題,而這些問題正是本文中著重討論的,以此來彌補協議層與應用層之間的差距。
WS-Reliability 標準的目標
WS-Reliability 標準的目的在于通過定義客戶機服務器之間的通信機制,使得 Web 服務滿足如下要求:
- 提供可靠消息傳遞( 至少一次語義)
- 除去重復消息( 至多一次語義)
- 確保消息次序
WS-Reliability 定義的消息關鍵元素
WS-Reliability 提出了一種基于消息/確認(message/acknowledgment)模型的可靠性解決方案。這意味著每個消息發送者在發送一條消息后都會等待從服務器返回的一條回應消息-確認。
圖 3: WS-Reliability 中的日志消息/確認模型
圖 3顯示了 WS-Reliability 規范中定義的一個消息場景。這里我們使用消息來取代 日志消息。 WS-Reliability 并不是特定日志消息而是適用于通用消息。但從我們的角度重發,我們只考慮日志應用程序。 #p#副標題#e#
一個日志客戶端發送一條日志消息給 Web 服務, Web 服務接收到日志消息后,如果有必要的話除去重復的消息,然后對消息進行處理。一旦處理完畢,它將發送一條確認消息給客戶端。
由于這篇文章不是用來專門討論 WS-Reliability 標準,因此,我們不會討論整個標準,但將會討論其中的幾個關鍵元素,特別是與可靠日志服務相關的特性元素。
首先,日志請求消息中包含的關鍵元素如下所示:
- Message-ID: 這是在消息發送前被指派的序號。通過這種方式, Web 服務在一條消息被重復提交多次的情況下能夠避免重復處理,同時還能夠保證消息之間正確的次序。
- Ack-Requested: 這一元素允許客戶端來決定對于發送的消息是否需要確認。對于一個可靠的日志 Web 服務,這一屬性標志必須為真。
- Duplicate-Elimination: 根據這一屬性,客戶端可以決定服務器是否需要進行去除重復消息的處理。對于一個可靠的日志 Web 服務,這一屬性標志必須為真。
確認消息中唯一一個重要的元素是字段 Ref-To-Message-ID 。 這一字段包含了確認消息所回應的日志消息的序號(Message-ID)。
從上面列出的幾個元素你可以看到, WS-Reliability 規范覆蓋了 “可靠日志的需求”一節中提出的 3 個需求。上述特性提供了可靠日志在協議層的解決方案,但并沒有提供應用層的解決方案,如可靠日志第 4 個需求,但它為解決應用層的問題提供了基礎。
在下面一節,我們列出了在應用層可能發生的錯誤,并提出了一個可以解決這些錯誤問題的解決方案。
日志在應用層的可靠性問題
為舉出應用層的可靠性問題,讓我們重溫回顧一下 圖 3中的日志場景:
- 客戶端對服務器發出日志請求
- 服務器接受到日志請求
- 服務器序列化日志請求
- 服務器發送確認給客戶端
- 客戶端接收到服務器發送的請求信息
上面的流程整體上提供了一種可靠消息傳遞機制:一個客戶端發送一條日志請求,服務器在完成消息存儲之后發送一條確認信息。但上述流程并不是意外安全的,因為在下述情形下上述流程將被打破,隨之而來的便是沒有確認消息返回到客戶端:
- 如果客戶機無法定位服務器怎么辦?
- 如果請求消息丟失怎么辦?
- 在存儲或尚未存儲日志信息的情形下,服務器崩潰怎么辦?
- 如果確認消息丟失怎么辦?
- 如果客戶機崩潰怎么辦?
在上述每一種情況下,你都必須保證日志消息被存儲且客戶端接收到確認消息。在某些條件下要確保這一點可能會很困難。下面我們將對上述情況進行詳細討論
客戶機無法定位服務器
如果客戶端不能夠定位服務器,則將導致日志服務失敗。但這個問題客戶端可以進行控制,因此,服務器端或協議層不需要特別的機制來處理這一狀況。
如上所述,日志信息在被日志客戶端提交到服務器端后絕不能夠丟失。如果客戶端不能夠定位服務器,將出現下面兩種情形:
- 服務器暫時無法連接。
- 服務器永久無法連接,或至少看起來如此。
設計一個基本的假設是:服務器的連接狀況對于業務應用程序盡可能透明。
在第一種情形下,日志客戶端能夠針對服務器無效的狀況對業務應用程序保持透明。日志客戶端將從業務應用程序接收的日志信息重復(使用同一個序號)發送,如果客戶端遇到的是服務器的瞬間故障,一旦服務器功能回復,它將馬上處理日志信息。
如果在 n 次嘗試后仍無法連接服務器,客戶端有理由認為服務器永久無法連接,因此需要將這一狀況報告給調用日志客戶端的業務應用程序。
請求信息丟失
在某些情形下客戶端和服務器之間的消息可能會丟失,如傳輸層上的包或當一個消息在一個跳轉鏈上進行傳輸時,其中的一個跳轉突然崩潰。
做為一個設計特色,消息確認使得客戶端能夠確定請求信息是否丟失。如果請求信息在發送到服務器的途中丟失,或者服務器在處理請求信息之前崩潰,那么客戶端不會接收到請求消息。
為了避免客戶端與服務器間的臨時連接超時的影響,客戶端將重復發送 n 次消息,如果這種連接超時依舊存在,客戶端在重復發送了 n 次后將停止重復發送日志信息并向調用客戶端的業務應用程序報告這一錯誤。
服務器故障
如果服務器發生故障,客戶端將從服務器得不到確認信息,將有可能發生兩種情形:
- 服務器在接收到信息之后但在存儲信息之前崩潰。
- 服務器在存儲信息之后但在發送響應信息之前崩潰。
在上述兩種情形下,你都希望客戶端能夠重新發送日志信息給服務器而且這些信息不會被服務器多次處理。就像你希望任何服務器上的故障對客戶端都是透明的一樣。
在第一種情況下,由于消息尚未被處理,客戶端只需要簡單的提交信息,而服務器端不需要采取任何特殊行為。
下面考慮第二種情形,你會注意到當第一次發送的消息被再次提交,則日志消息將會被處理 2 次,因為這條日志信息已經被記錄了。因此,客戶端必須能夠保證在服務器不會第二次處理消息的前提下重復提交信息。為解決這個問題,服務器必須包含一個狀態變量來標識提交的消息已經被處理但確認消息尚未發出這一狀態。
在協議層,架構方案為解決這一問題提出消息序號,或在 WS-Reliability 被稱為的 Message-ID ,根據消息序號和服務器端的存儲日志,服務器能夠鑒別處重復提交的日志消息。
根據這個架構,你可以看出日志 Web 服務根據需要進行工作,不會將已經提交的信息進行重復處理。一個日志客戶端提交信息給服務器。服務器接收到信息,然后檢查存儲日志來判斷這條信息是否在之前已被處理。如果尚未被處理,換句話說,存儲日志中不存在對應的條目,服務器將處理日志信息,如果處理成功,在返回確認消息之前,將在存儲日志中創建一個條目。如果消息已經被處理,換句話說,存儲日志中存在對應的條目,則服務器將不會處理消息而是立即返回確認信息。
需要注意是,要使架構能夠正確工作,包含存儲日志的文件系統絕對不能夠溢出。
確認消息丟失
像日志消息一樣,確認消息由于某些原因也會丟失,同樣,客戶端無法確切知道哪里發生了錯誤。然而,像上面提到的,通過使得服務器具有容錯性,客戶端可以簡單的重新發送日志消息來等待確認信息的到達。
為將暫時錯誤與永久錯誤區分開,客戶端可以采用與上面所述的同樣的策略。客戶端發送 n 次日志信息。如果在發送 n 次信息后仍舊沒有接收到確認消息,客戶端有理由認為系統遇到永久性故障,它可將這一故障信息返回給調用者或業務應用程序。
客戶端崩潰
對于可靠日志來說,日志客戶端將是一個業務應用程序的主要組成部分。業務應用程序的許多操作或任意操作都伴隨著日志操作。由于日志客戶端的同步特性,如果日志應用程序運行失敗則業務應用程序同樣也會失敗。
提出的架構
組件
根據上節中討論的內容,我們提出如 圖 4 所示的架構.
圖 4: 日志客戶端和服務器架構
客戶端提供了一組 API,業務應用程序通過它能夠訪問日志客戶端。控制器包含日志客戶端的業務邏輯。在客戶端的底層,你將發現客戶端使用的實現了傳輸協議的通信 API。
服務器包含一組通信 API 用來與客戶端進行通信,一個存儲日志用來保存狀態,還有一個日志消息倉庫。為實現上一節所講的業務規則,通過一個控制器組件將服務器內的所有組件緊緊聯系在一起。
日志需求與體系結構的關系
在對本節進行總結之前,讓我們看一下體系架構是如何滿足前面所述的日志需求的
- 實現可靠的消息傳遞:請求/確認協議使得客戶端能夠判斷消息是否傳遞到客戶端。
- 除去重復消息:由于服務器包含一個狀態變量,因此重復的日志消息能夠被除去。
- 確保消息次序:由于日志客戶端的同步特性,如果沒有接收到前一條日志消息的確認信息,日志客戶端將不會發送新的日志消息,日志消息將按照正確的順序依次處理。
消息編號
在所提出的架構中還有一個重要但尚未進行討論的設計特征,那就是消息編號。對于所提出的架構來講,實現消息編號的一個最佳方法便是將 HTTP 會話 ID 與發送消息的時間戳進行組合。時間戳的保證了不同的日志消息具有唯一的序號。根據 HTTP 會話 ID ,服務器能夠區分出哪一條消息是來自哪一個客戶端,這一點對于重復消息的去除和并發的客戶端間的區別至關重要。
事務語義支持的日志
一個事務性的運行環境確保一個應用程序的原子性、一致性、孤立性和持久性。這使得并行運行的應用程序在訪問共享資源時得到保護,避免由于資源沖突而產生的資源沖突甚至崩潰。如果一個應用程序發生崩潰,那么他的所有操作將會被回退(原子性),如果一個應用程序成功,那么他的所有操作將被保證成功(持久性)。事務系統能夠確保資源保持一致性,即使資源被同時訪問(一致性)。事務系統同樣能夠保證應用程序的運行可以不管其它應用程序的運行情況,就像它自己在單獨運行一樣(獨立性)。
日志對許多應用程序來說是都是一個重要的組成部分,至少存在兩種類型的日志。 一般信息日志主要用來跟蹤應用程序的步驟和操作。根據日志信息的用途,它對應用程序的操作有著或輕或重的影響。例如, 如果日志記錄只是用來進行統計分析,少數幾次失敗的日志操作將是可以接受的。然而,如果日志是用來審計, 那么遺失日志記錄將是不可接受的。
另外一種日志稱為關鍵業務日志。它將影響到應用程序中與業務相關的其它部分。其它應用程序將讀取關鍵業務日志并應用到它們的商業邏輯中。這種類型的日志將像其它的一些業務操作一樣來被謹慎處理。例如一個財務日志記錄,里面記錄財務轉帳信息,而且這一日志被用來進行投資興趣分析或納稅憑證。
在本文中,我們定義了一個事務語法支持的日志服務,重點解決原子性語法。者并不意味者我們強制所有的日志行為做作為原子事務的一部分,而是根據日志信息是否事務敏感,我們可以給應用程序提供相應的事務語法支持。
事務性執行
如果有幾個應用程序在并行運行,它們中的每一個都要執行一系列連續的操作,那么整個系統的執行過程就包括按照一定次序執行的、來自不同應用程序的不同操作。如果這些應用程序訪問共享數據,它們就將導致破壞一致性的潛在沖突的產生。數據庫系統中的一致性概念和預測鎖定(請參閱 參考資料)對并發環境中的一致性問題給出了明確定義。數據庫系統的并發控制和復原(請參閱 參考資料)給出了防止系統產生不一致問題的正確操作的屬性。
原子性
原子性可能是一個成功事務執行的最基本屬性。一個事務執行被稱為一個原子是指它的所有更新操作要么全部成功,要么全部失敗,這一點通常被稱為 all-or-nothing 屬性。如果你假設一個事務總是一個一致性的工作單元,整個系統的所有更新都被執行,很顯然系統仍能夠保持一致性。當一個事務執行已經開始執行但尚未完成,只有一部分更新操作被實際執行,你就不能假定整個系統的狀態仍舊是一致的。你只有在系統的所有操作都被執行或都不被執行時,才能假設整個系統是一致的。
作為事務的基本屬性,原子性被各種系統實現。在分布式系統中,原子性還表明一個事務應該在參與事務的所有節點中全部執行成功或全部失敗。為確保這一點,兩步提交協議(請參閱 參考資料中的 分布式數據庫原理)被提出且在各種系統中實現。#p#副標題#e#
原子性日志操作
你可以將日志操作分為以下 3 類:
- 不涉及事務原子性的日志操作。一個日志操作的失敗不會導致整個事務的失敗,并且即使在事務被中止的情況下日志操作仍舊可以成功。這類日志操作不需要消耗事務管理資源,也不需要日志服務支持事務
- 可視為其它更新一樣參與原子事務的日志操作。如果操作失敗,整個事務過程需要回滾,并且只有在整個事務執行成功的前提下,日志操作才視為成功執行。
- 半事務原子性的日志操作。只有當事務提交的時候日志操作才會成功,但日志操作的失敗并不會導致事務被中止。在那種情況下,一些日志記錄將會丟失,但日志存儲并不會因為被中止的事務的記錄而被“污染”。換句話說,并不存在臟寫的記錄。這種操作類型是在原子性和事務帶來的巨大代價之間的折中。因為如果日志操作失敗,并沒有正常的事務操作受到影響,但如果事務失敗,日志消息卻會受到影響。
對于分布式計算來說, Web 服務是一個相對較新的消息基礎設施。 Web 服務的事務性還沒有得到相應的重視。最近, Web 服務組織就分布式事務如何與 Web 服務架構相協調提出 2 個草案 (商業事務和 Web 服務事務 -- 請參閱 參考資料)。這里我們不對這兩個草案進行比較,相反,我們主要討論 WS-Transaction 規范,因為它是一個更有發展前景的方案,但我希望你將這兩個草案都閱讀一下來形成你自己的觀點。WS-Transaction 規范在分布式事務的參與者間定義了一個兩階段提交協議來支持事務原子性。
WS-Transaction
WS-Transaction 規范應用于基于 Web 服務的分布式系統。應用程序之間、應用程序與系統服務之間以及系統服務之間都是通過 Web 服務進行通信。規范以 Web 服務描述語言描述了原子性事務協議。協議內容如下:
- 完成: 應用利用此協議來初始化分布式事務提交循環。
- 兩階段提交: 首先參與分布式事務的應用程序必須延緩自身的更新。當完成指令被請求,一個協調器將向所有的事務參與應用程序發出一個 Prepare 消息。在接收到 Prepare 消息后,每個應用程序根據被延緩的更新是否可以提交來返回 Prepared 消息或 Aborted 消息。如果事務的所有參與者返回的都是 Prepare 消息,則它們將得到一個提交指令,這將導致所有的更新被提交,否則它們將得到一個放棄消息,所有被延緩的更新將被放棄。
- 階段 0: 一旦一個兩步提交循環開始,應用程序除了 Prepare 、Commit 和 Abort 指令外,不再執行任何操作。假設一個在緩存中包含若干更新的服務最終需要將更新存儲到數據庫中,那么它將需要調用一個數據庫服務。由于應用程序在接收到 Prepare 指令后將禁止調用數據庫服務,那么服務如何在 Commit 之前存儲數據呢?這將通過階段 0 協議來實現。在開始 Commit 循環之前,協調器將給參與者發送一個階段 0 消息。
- 結果通知: 一些不屬于分布式事務的應用程序僅僅想知道事務執行結果:提交還是放棄。它們可以通過結果同志協議獲取這一信息。
WS-Transaction 規范建立在另外一個協議 WS-Coordination(請參閱 參考資料)之上. 上述 2 個協議都是以協議協調器和協議使用者之間的 Web 服務接口的形式來實現的。因此,存在必然存在兩階段提交協調服務和兩階段提交使用服務,階段 0 協調服務和階段 0 使用服務等等。這些協調服務和參與服務在 WS-Transaction 規范中通過 Web 服務描述語言( WSDL)以端口類型的形式來描述。
事務支持的日志服務架構
圖 5: 事務支持的日志服務架構
圖 5 展示了一些參與節點和協議以及它們之間必要的交互。我們假定有 2 個應用程序節點( Appl1 和 Appl2 ),一個數據庫節點( DB ),和一個包含日志服務的節點( LogService )。
節點及其服務
- Appl1 是一個初始應用程序,它希望完成分布式事務,因此它向協調器注冊事務的完成協議。因此它將參與服務提供給完成協議( P-C )并使用協調器的服務來使用完成協議。它同樣可以使用日志服務節點上的日志服務( Logging ),發送不同事務原子級別的日志信息。另外,它還向節點 Appl2 發送應用程序信息,向數據庫節點 DB 發送數據庫請求。
- Appl2 被 Appl1 初始化并為 Appl1 工作。它在本地內存中緩存了許多更新,并希望最終將這些更新輸送到數據庫中,因此它通過協調器注冊階段 0 協議,因此必須將提供參與服務給階段 0 協議 ( P-pz )。
- DB 是數據庫節點,它負責接收應用程序的更新,因此它作為一個參與者來注冊兩階段提交協議。因此它必須提供參與服務( P-2pc )。
- LogService 是一個日志服務節點。它負責接收日志服務,每一個日志消息可能具有不同的事務原子級別。如果某個日志消息是事務原子性或半事務原子性,日志服務必須作為一個參與者來注冊兩階段提交協議,這樣她就必須提供參與服務給兩階段提交協議( P-2pc )。根據不同的緩存策略,它可能還需要注冊階段 0 協議來將日志消息存儲到數據庫中在事務完成之前。
- Coordinator 是一個 WS-transaction 協調節點,它提供如下協調服務:完成協議、階段 0 協議、兩階段提交協議、C-c、 C-pz、 和 C-2pc。
消息順序
由于篇幅限制,我們這里對參與者與協調器之間的協議注冊消息不加討論,你可以在 WS-Coordination 規范(參見 參考資料)中獲取更多相關信息。在隨后的討論中,我們假定每一個節點對于它使用的協議都已經成功的注冊了協調器。
必須說明的是,對于 WS-Transaction 定義的每一條消息,都同時還包含一個事務協調上下文。因為當消息通過 Web 服務環境傳輸時,事務協調上下文被包含在 SOAP 頭中,規范中的上下文具有可擴展性,你可以通過一個代表日志消息所需的事務原子性級別的元素來對它進行擴展。這個指定的級別可以是空、半原子性和原子性。需要注意得是,任何消息都包含事務協調上下文,不管是應用程序間的消息還是應用程序發送給數據庫的消息。
- 應用程序與應用程序間存在消息,應用程序與數據庫服務間存在消息,應用程序到日志服務間存在消息。每一個日志消息在事務協調上下文都包含指定的事務原子性級別信息。日志服務器總是檢查這一信息。如果指定的級別是原子性或半原子性,日志服務不會將日志消息馬上進行持續化處理,相反,它將這些日志信息保存在安全的地方,在提交過程中再將這些信息取回。如果事務原子性級別是空,日志消息將被立即寫入永久性日志媒體中。
- 節點 Appl1, 初始化應用程序,決定完成工作,因此調用協調器的完成服務 (C-c)。
- 在初始化兩階段提交循環之前,協調器調用 Appl2 的階段 0 參與服務。作為對此消息的響應, Appl2 通過數據庫服務寫入緩存的更新并將這一階段 0 的成功報告給協調器。如果 Appl2 沒能夠完成階段 0 ,協調器將會取消整個事務。
- 如果階段 0 成功,協調器將開始兩階段提交循環:
- 協調器調用 LogService 和數據庫服務器的 Prepare 操作。日志服務器檢查日志服務是否準備好將所有事務原子性(不是半事務原子性)的日志消息持久化,如果檢查失敗,將向協調器報告 Abort 信息,否則報告 Prepared 信息。向協調器發送 Prepared 消息就好比作個可以提交的承諾,因此事務原子性的日志消息必須預先存儲到穩定的存儲器,這樣 隨后的提交即使日志服務在期間崩潰仍舊可以完成。
- 如果每個參與者報告 Prepared,協調器將向每一個參與者發送 Commit 消息。然后日志服務器持久化所有事務原子性和半原子性的日志消息。如果持久化順利完成,則向協調器報告 Commit。
協調上下文
在 WS-Transaction 規范中協調上下文被定義為一個事務相關的頭信息的容器, 清單 1 給出了 SOAP 頭中的協調上下文的結構。上下文結構包含一個元素 ,
, 指定上下文的類型,它是一個 WS-Transaction URL。它說明這一協調器上下文包含一個 WS-Transaction 協議消息 。在上下文內部,我們引入新的元素 ,
,其中的命名空間是假定的,元素的值是日志信息指定的事務原子性級別,它可以是空、原子性或半原子性。
清單 1
|
結束語
這篇文章指出日志是現代業務應用程序中的一個重要部分,需要像應用程序中其它的與業務相關的部分一樣謹慎處理。如果業務需要日志作為企業及其處理流程的一部分,那么一個集中的日志服務便應需而生,因此日志 Web 服務是一個理想的選擇。