加入RUN!PC粉絲團
 
精選文章
 
實用SQL Server 2008(5)
資料庫訊息交換平台Service Broker(上)
文/圖 胡百敬.責任編輯/洪羿漣

SQL Server 2005版後新增了Service Broker服務,藉以提供強固穩定的訊息平台,讓系統間交換訊息多了一個選擇。換個角度而言,就是提供服務導向架構(Service-Oriented Architecture;SOA)在資料庫平台的支援。讓你在建立鬆散偶合(loosely coupled)結構的分散式應用程式時,可以根基於成熟的資料庫技術。

不管是SQL Server內部的物件,或是外部的程式都可以透過Service Broke平台交換訊息,非同步地讓資料庫物件彼此溝通,或是跨資料庫、跨SQL Server執行個體,乃至於跨伺服器間溝通。

非同步架構可以提升整體系統合作的彈性,例如A系統的運算力強悍,需要即時處理大量的需求,但它一天之中只會在某些時段很忙碌(例如線上訂貨系統、不斷觸發事件的系統),同時輸出一些資料給B系統。

B系統的工作不需要即時完成,但必須保證在一段時間後處理完畢(例如物流配送系統、分析執行記錄的監控系統)。則B系統就可以搭配訊息佇列來非同步處理需求,但其運算力不需要非常強悍,透過時間與排程順序換取工作執行,它可以長時間持續地消化A系統短時間產生的大量工作。

佇列在非同步運作的架構中是很常用的資料結構,它的實作並不困難,甚至你只要呼叫 .NET提供的System.Collections.Queue類別即可,也不需要自己寫佇列。但要建構開放而標準的架構,讓各式應用程式都可以透過它整合,則可信賴的穩定性、擴充性、安全性、標準的程式存取介面、交易管理、訊息繞送…等需求應運而起,這非我們一般程式設計師可以輕易建構的。

Service Broker就是以資料表來模擬佇列,於SQL Server執行個體間支援訊息繞送,提供標準的T-SQL操作方式,讓系統開發人員可以善用訊息溝通的特色設計應用程式,並整合SQL Server Management Studio,讓管理者可以設定與監控Service Broker的運行。

Service Broker有以下的特色:


訊息保證寄達

Service Broker會為每則訊息提供標示,保證訊息一定寄達目的,並依照訊息先後的發送順序;依次傳達給處理訊息的應用程式,並只送達一次。我們的應用程式只需要收發訊息,不需要考慮訊息品質,全部交由Service Broker。


透過交談(Conversation)協調相關的訊息

當處理相關的訊息時,透過交易與鎖定的機制,Service Broker會將同一交談群組(Conversation Group)的訊息一起鎖定,因此只有一個處理訊息的服務程式執行個體可以在交談內,從佇列(Queue)中取出相關聯的多個訊息,並完成訊息的處理。而其他的執行個體依然可以透過該佇列取出不在此一交談群組的其他群組訊息。


非同步發佈

Service Broker可以提供非同步的訊息處理機制,所以使用者發送端應用程式可以傳送訊息後就逕行執行自己接下去的工作。不必等待對方接收端服務提供者回覆。而接收端服務提供者也不必在當下已經啟動執行,訊息會留在佇列中。SQL Server 2005後提供的Database Mail功能就採用這個架構。


彈性地排程處理

Service Broker可以等系統不忙碌時,才處理訊息。例如,搭配Agent Services的排程工作,利用晚上閒暇時處理佇列中的訊息。因為訊息本來就是非同步處理,起始端應用程式不需要知道訊息何時會被處理。


自動叫起處理程式

Service Broker會根據佇列中的訊息數量自動叫起對應的服務程式。如果一個應用程式的執行個體不足以處理已經收到的訊息,Service Broker會自動叫起多個執行個體來處理,當訊息量減少時,Service Broker會自動減少提供服務的應用程式。如果系統重起,Service Broker會視狀況是否要重新叫起提供服務的應用程式。


自行撰寫訊息佇列應用程式

在自行撰寫訊息佇列應用程式時,這是比較麻煩的一件事情,為了在多CPU的伺服器上有效地處理佇列中的一大堆訊息,可能會採用多執行緒的方式來撰寫應用程式,這時就需要小心「佇列」這個共用資源的同步與鎖定問題。而Service Broker會自動幫我們處理掉這個問題。


資料庫整合

Service Broker將訊息、佇列以及其他相關的項目整合到資料庫中,可以讓整個訊息機制搭配交易處理。例如將收到訊息、處理訊息和回覆訊息的動作全包在一個交易中。若交易失敗,則訊息保留在佇列中,讓處理的程式有機會再重新來一次。


資料安全

對於管理者來說,由於Service Broker是以資料庫為基礎來存放相關的資料,因此管理者只要做一般的備份與還原工作即可,不必為Service Broker另建備份機制。支援叢集與資料庫鏡像。交談可以透過系統重新啟動、伺服器容錯移轉、網路中斷等進行維護,而不會讓資料受損或遺失。


安全的溝通

Service Broker可以藉由憑證(Certificate)的鑰匙對(Key Pair)來加密傳輸的資料(實際的加解密機制是仿效HTTPS/SSL的作法),並透過Windows使用者帳號或是憑證(Certificate)來確認身分,以避免SQL Server執行個體接收惡意或錯誤的訊息。


分散式地處理

Service Broker可以定義繞送(route)路徑和遠端服務繫結(Remote Service Bindings),讓多台資料庫伺服器間可以彼此交換訊息。

簡單討論完Service Broker架構特徵後,接下來說明建置與使用Service Broker所需實做的物件定義。由於訊息的規範,以及通訊端點間的鍊結全靠我們自行定義,剛開始入手需要耐心,因為它較MSMQ平台麻煩,但它更為開放,較少綁定Windows平台(當然,它綁在SQL Server,就已經綁在Windows了。我的意思是,它沒有綁AD)。


Service Broker架構與組成元件
在撰寫T-SQL建立Service Broker應用程式之前,必須要了解數種包含在Service Broker架構中的SQL Server物件。簡略說明如下:
1. 訊息類型(Message Type)

服務的使用者(Service Consumer)送訊息到服務提供者(Service Provider),兩者必須同意它們所交換的訊息型態(Message Type),並確定如何確認(Validate)該型態。在使用者與提供者間建立一致的訊息型態。

2. 合約(Contract)

合約物件定義完成工作所需的訊息型態,並規範誰可以送哪種訊息型態,它以如下的方式定義誰可以送訊息:
●Initiator:起始端(Initiator endpoint)是開啟對話(conversation)的端點(endpoint),這個設定要求只有起始端可以發送預先定義好的某種訊息型態。
●Target:目標端(Target endpoint)是從起始接收對話(conversation)的端點,這個設定要求只有目標端可以發送預先定義好的某種訊息型態。
●Any:某些訊息是兩者都可以發送的。

必須要在提供者與使用者資料庫間建立相同的Contract物件。

3. 佇列(Queue)

Service Broker發送訊息到服務,服務將訊息存放在佇列。當服務提供者的伺服器當下不存在時,服務使用者可以將訊息存在本機的佇列中。Service Broker會重複嘗試,直到成功送達該訊息到服務提供者的佇列後才從本機佇列中將訊息移除。如果服務提供者與使用者在同一個SQL Server執行個體上,則只使用一個佇列。

在Service Broker架構中是用資料表來實做佇列,而進入佇列的訊息則是一筆筆的記錄。每一筆記錄除了有訊息本身的資訊外,還記載著交談識別碼(conversation identifier)以及與合約相關的資訊。

你可以設定當訊息送達到佇列後,Service Broker就自動啟動處理訊息的服務程式執行個體,且可以視該執行個體是否能夠及時處理完訊息而同時啟動多個執行個體來提供服務。

4. 服務程式(Service Program)

服務程式發出要求或提供服務,並在架構中依據商業邏輯寄發、接收與處理訊息。服務程式一般是以指定預存程序的方式設定,透過T-SQL或 .NET程式語言撰寫該預存程序皆可。

你可以設定Service Broker在訊息到達佇列時,自動啟動服務程式。或是依照排程定時啟動服務程式,則該服務程式執行個體是在伺服器之內的預存程序;還是外部應用程式皆可,啟動後再讀取佇列中的訊息。

服務程式也經常需要寄一個回覆訊息給交談起始端的起始程式,而必須要透過交談機制讓回應正確。

5. 服務(Service)

存在SQL Server的邏輯定義。它必須指定一個佇列,以存放寄送到該服務的訊息。並可選擇性地定義合約列表,以限制寄送到自己的訊息型態。服務組合著實體的佇列、繞送訊息的路由定義,同時擁有該服務和用於加/解密的憑證之資料庫使用者等。

6. 交談(Conversation)

服務間的溝通都泛稱交談。以BEGIN DIALOG CONVERSATION(可惜的是SQL Server 2008版依然沒有單向的對話(monolog),所以本篇文章的範例在收集訊息端,需要回復訊息並結束對話可以參照http://social.msdn.microsoft.com/forums/en-US/sqlservicebroker/thread/8595bf6c-39d5-4f8a-be74-f2d011d640d3/)建立,且是應用程式開始使用Service Broker的方式。
● 對話(Dialog):兩個服務間一對一的傳遞訊息方式稱為對話。定義兩個服務節點間溝通的規則,也就是從哪個服務(From)遵守什麼樣的合約;傳遞訊息給另一個服務(To),並以一個GUID格式的dialog handle來代表這個規則,透過SEND語法寄送訊息時會用到這個handle。對話的生命週期可能長達數年或短於數秒,並可永久儲存在資料表內,也就是當系統停機重起後,對話依然存在。 「對話」保證訊息寄達,且只寄達一次,同時維護安全通訊,加密其中溝通的資料,以及服務所收到訊息的相關性與順序。開啟對話的語法約略如下:



服務透過交談彼此溝通,但與溝通相關的設定還有下列3項:
●交談群組(Conversation Group):使用者用來定義一組交談彼此相關的群組,是以一個128位元的UUID值來代表。
●路由(Routes):在不同SQL Server的執行個體間傳遞訊息需要定義繞送路徑。這種分層獨立的設定方是可以讓相同的服務定義;若要在不同的SQL Server執行個體間傳遞,只需修改路由即可,不需要變更其他設定。
●遠端服務繫結(Remote Service Bindings):將遠端服務與當下資料庫的使用者(User)帳號做個連結,利用該使用者所擁有的憑證,以設定遠端服務的授權與加密。

結合以上所述,Service Broker的邏輯架構如圖1所示,而筆者也將以這個架構,設計三期專欄的範例。

圖1:Service Broker的邏輯架構圖。


SQL Server 2008版繼續強化Service Broker的功能,其新增的主要功能如下:

1. 交談優先權:讓重要的訊息在不重要訊息之前傳送及接收。以確保優先順序低的工作不會阻擋優先順序較高的工作。藉此提供各種服務層級。

2. 新的命令提示字元公用程式ssbdiagnose:診斷Service Broker組態與交談。分析兩個Service Broker服務之間或單一服務的組態。此公用程式也會分析正在執行之交談中的錯誤。如果執行中的交談遇到錯誤,ssbdiagnose也會分析此交談所使用的Service Broker組態。可在命令提示字元視窗中直接呈現錯誤、重新導向檔案或其他格式化的XML。

3. 新的效能物件和計數器:
●Broker TO Statistics效能物件會報告Service Broker對話要求傳輸物件的頻率,以及非使用中傳輸物件寫入tempdb中資料庫工作資料表的頻率。
●Broker Statistics效能物件中加入下列五個新的計數器:Activation Errors Total、Corrupted Messages Total、Dequeued TransmissionQ Msgs/sec、Dropped Messages Total、Enqueued TransmissionQ Msgs/sec等。

4. SQL Server Management Studio中呈現更為詳盡的Service Broker物件。

接下來以跨SQL Server執行個體蒐集事件資訊為範例,說明透過Service Broker傳遞訊息的方式。


Service Broker的應用範例
整個範例的架構如圖2所示,在此範例中,例用DDL Trigger將左方伺服器發生的事件,透過Service Broker傳送到右方SQL Server執行個體。右方資料庫內的佇列收到訊息後,透過自動啟動預存程序,將訊息從佇列讀出存放到資料表中。

圖2:透過Service Broker將多個SQL Server執行個體所發生的事件集中存放到一個遠端的資料庫。


Service Broker要跨SQL Server執行個體傳送訊息,首先需在執行個體上建立端點(End Point),端點有如進出SQL Server的大門,我們習慣透過TSQL存取SQL Server,走得就是TSQL端點。SQL Server 2005後還新增了SOAP、Database Mirroring和Service Broker等端點。

端點是SQL Server執行個體等級的物件,可以透過sys.endpoints系統檢視觀察。(未來版本的的SQL Server將會不支援SOAP端點。在新的開發工作中請避免使用此功能,並且規劃修改目前使用此功能的應用程式。)

在定義各資料庫內的Service Broker物件前,需在SQL Server執行個體建立用於Service Broker溝通的端點。目前可用於Service Broker端點溝通的通訊協定僅有TCP/IP,在定義時需告知要聆聽的通訊埠(Port)號碼,如範例程式1,在SQL Server執行個體上建立端點,以利Service Broker溝通。



Service Broker在SQL Server執行個體的端點間溝通時,必須認證身分(Authentication),並支援兩種認證方式,一是採用Windows帳號認證,另一是透過憑證。筆者在範例程式1中同時表列了兩種方法,若使用Windows帳號驗證,其設定方式較簡單,但跨機器間溝通需要配合AD(Active Directory),範例中列出了語法,但標示成說明供你參考。

此範例實際採用的是憑證來驗證身分,程式中先建立伺服器等級的憑證,並將其備份到硬碟檔案中,以安裝到接收端的伺服器執行個體,方便兩端點認證身分。這僅是兩個執行個體用在接收與傳送資料的端點使用,進一步的授權和加解密則需定義在資料庫內各Service Broker的服務上。

在端點間傳送的資訊可以透過ENCRYPTION選項設定是否需要加密,預設值是REQUIRED,可用的設定選項如下:
ENCRYPTION = { DISABLED | SUPPORTED | REQUIRED } [ALGORITHM { RC4 | AES | AES RC4 | RC4 AES } ]

簡單說明各選項如下:
●DISABLED:透過連接傳送的資料不加密。
●SUPPORTED:只有在相對端點指定為SUPPORTED或REQUIRED時才加密資料。
●REQUIRED:必須加密。若要連接這個端點,其他端點必須將ENCRYPTION設為SUPPORTED或REQUIRED。

實際在端點間傳輸的訊息加密與否,需看兩者對「ENCRYPTION」的設定,表列可能的結果如表1。



另外,在CREATE ENDPOINT陳述式中,也可以選擇性地利用「ALGORITHM」引數來指定端點使用的加密演算法,如RC4、AES等。微軟建議採用AES。如果兩個端點都指定了這兩種演算法,但指定順序不同,例如一邊設定RC4 AES,另一方是AES RC4,則以接受連接的端點為準。

建立完Service Broker端點後,透過sys.endpoints系統檢視查詢的結果如圖3。由於筆者故意在執行個體中建立了各類型端點,所以圖3呈現了不同端點的中繼資料。

圖3:經由sys.endpoints系統檢視查詢執行個體上已經建立的各類端點。


在SQL Server Management Studio的「物件總管」視窗內,其「伺服器物件」→「端點」節點下,可以看到SQL Server執行個體上已經建立的各類端點,如圖4。

圖4:經由SQL Server Management Studio的「物件總管」視窗查詢執行個體上已經建立的各類端點。


接下來建立寄送訊息的資料庫與用來加解密訊息的憑證,如範例程式2,在資料庫內建立憑證,以加密Service Broker溝通的訊息。



Service Broker間的溝通需交互認證、授權與加密,都要靠憑證資訊來輔助完成。因此在範例程式2中,先建立憑證並備份到檔案,以複製到另一端執行個體安裝,當然,你也可以使用一般發證中心所發的正式憑證。

由於Service Broker的服務無法擁有憑證,需要使用者才可以擁有憑證,所以需在範例程式碼2中建立使用者,同時擁有憑證和服務,則服務可以間接地透過擁有它的使用者取到可解密和簽章的憑證。

限於篇幅的關係,只能先介紹到此,在下2期專欄中,再繼續完成範例程式,並說明如何檢視相關的中繼資料和除錯。



【原文刊載於RUN!PC雜誌:2009年7月號】