Service Broker學習(一)


0.參考文獻:

SQL Server Service Broker MSDN文檔總覽

SQL Server 2005 Service Broker 初探

Servic Broker對話會話

1.Service Broker 編程

Service Broker 功能通過 SQL Server 中的新對象啟用,這些新對象可以由一組 T-SQL 擴展來創建和操作。為了數據庫程序員的方便,使用了他們熟悉的用於配置其他數據庫對象的 CREATE、ALTER 和 DROP DDL 語句來配置 Service Broker 應用程序。用於創建 Service Broker 對話以及在對話中發送和接收消息的命令是 Transact SQL 語言的 DML 擴展。接收命令的語法與選擇命令相似,它返回包含消息的行集,就像選擇命令返回包含行的行集一樣。熟悉 Transact SQL 編程的開發人員會發現學習 Service Broker 編程非常容易。用於為 Service Broker 編程的客戶端 API 與用於為所有數據庫編程的 API 相同,例如 OLEDB、ODBC、ADO、ADO.NET 等等。下面是 Service Broker 使用的對象。

1.1.隊列(QUEUE)

Service Broker 使用隊列在消息發送程序和消息接收程序之間提供松散耦合。發送程序可以使用 SEND 命令將消息放到隊列中,然后應用程序繼續操作(不用等待接受程序發送確認回復)並依靠 Service Broker 來確保消息到達其目標位置。

隊列允許較大的計划靈活性。例如,發送程序可以發送多條消息以供多個接收程序並行處理。接收程序可能在消息發送很長時間后才處理消息,但由於傳入消息進行了排隊,因此接收程序可以按其自己的速率處理消息,而且發送程序無須等待接收程序完成處理便可繼續操作

1.2.對話(DIALOG)

Service Broker 還實現了對話,對話是兩個端點之間的雙向消息流。對話中的所有消息都進行了排序,而且對話消息總是按照發送的順序傳送。該順序在事務、輸入線程、輸出線程以及系統崩潰和重新啟動過程中都保持不變。

對話是一種會話類型。Service Broker 會話是持久可靠的通信通道。在以后的 SQL Server 版本中,Service Broker 將包括一對多的單向會話,也稱為可靠的“發布-訂閱”。在 SQL Server 2005 中,對話是唯一的會話類型,因此這兩個術語同義。

每條消息都包括唯一標識與它相關的對話的會話句柄。例如,某個訂單輸入應用程序可能同時使用發貨應用程序、庫存應用程序和帳單應用程序打開了對話。因為每個應用程序中的消息都具有唯一的會話句柄,所以可以輕松地確定發送每條消息的應用程序。

下面的關系圖顯示對話的消息流:

1.3.消息類型(MESSAGE TYPE)

當前,所有 Service Broker 消息都與特定的消息類型相關聯。消息類型是與消息一起傳送的標簽,因此接收消息的應用程序可以確定所接收消息的類型。此外,如果消息包含 XML 文檔,則消息類型可以與 XML 架構集合相關聯。如果為某個消息類型指定了架構集合,則所接收的該類型消息將在收到時根據架構集合進行驗證,而沒有通過架構驗證的消息將會被拒絕。

1.4.規范(CONTRACT)

Service Broker 規范是一個消息類型集合。一個對話總是與一個規范相關聯,而規范定義哪些消息類型可以通過對話發送。

1.5.服務(SERVICE)

Service Broker 服務將一個或多個規范與一個隊列相關聯。規范定義可以將哪些消息類型發送到隊列。服務名稱用於建立對話的端點。服務名稱用作實際隊列的別名,因此您可以編寫引用服務名稱的 Service Broker 程序,然后在部署應用程序時將它與實際隊列相關聯。

2.Service Broker“Hello World”

大多數編程語言書籍都以“Hello World”示例開始,因此我們也在 Service Broker 中使用 Hello World 作為示例。為簡化示例,我使用可以從 SQL Server Management Studio 查詢窗口運行的 T-SQL 進行編寫。大多數 Service Broker 應用程序將作為普通的數據庫應用程序,這些應用程序由通過 ADO 或 ADO.NET 與數據庫進行通信的可執行程序和使用 T-SQL 或 .NET 語言編寫的 SQL Server 存儲過程構成。

要發送和接收消息,必須首先創建向 Service Broker 描述應用程序的消息傳送部分的元數據對象。在 SQL Server 2005 中,使用新添加的 DDL 語句來創建、修改和刪除 Service Broker 元數據。

代碼示例

View Code
-- step1
-- 創建要使用的數據庫
Create Database HelloWorldDB
go

Use HelloWorldDB
go

--step2
/*創建要使用的兩種消息類型。我們要使用的消息將是
  字符串而不是 XML,因此無需進行驗證 
*/
CREATE MESSAGE TYPE [HelloWorldRequest] VALIDATION = NONE 
CREATE MESSAGE TYPE [HelloWorldResponse] VALIDATION = NONE 

--step3:
/*創建一個限制此對話框中消息類型的規范。
  請求由對話框的初始化程序發出響應消息由對話框目標發送。
*/
CREATE CONTRACT [HelloWorldContract]
( 
    [HelloWorldRequest] SENT BY initiator,
    [HelloWorldResponse] SENT BY target
)

--step4
-- 創建對話框在其間通信的兩個隊列。A對話框請求兩個隊列。
CREATE QUEUE [HelloWorldTargetQueue]
CREATE QUEUE [HelloWorldInitiatorQueue]

--step5
-- 創建命名對話框端點的服務。服務會將會話端點連接到隊列。
CREATE SERVICE [HelloWorldRequestService] ON QUEUE [HelloWorldTargetQueue]
( 
    [HelloWorldContract] 
)
CREATE SERVICE [HelloWorldResponseService] ON QUEUE [HelloWorldInitiatorQueue]
go

--step6
/*現在已經設置了元數據,可以發送消息了。請注意,由於初始化程序和目標服務
  位於同一 SQL Server 實例中,因此消息將直接轉到目標隊列而不會通過傳送隊
  列傳送。由於 Service Broker 內置在數據庫中,因此可以進行此項性能優化。
*/
SET NOCOUNT ON
DECLARE @conversationHandle uniqueidentifier
Begin Transaction--事物開始
-- 開始 Hello World 服務的對話
BEGIN DIALOG  @conversationHandle
FROM SERVICE    [HelloWorldResponseService]
TO SERVICE      'HelloWorldRequestService'
ON CONTRACT     [HelloWorldContract]
WITH ENCRYPTION = OFF, LIFETIME = 600;
-- 發送消息
SEND ON CONVERSATION @conversationHandle 
MESSAGE TYPE [HelloWorldRequest] (N'Hello World')
commit--事物提交

--step7
--讓我們查看目標隊列以確保成功發送了消息。檢查目標隊列以確認消息已送達
select * from [HelloWorldTargetQueue]
go
-- 將消息主體轉換為字符串,以便我們查看其中包含的內容
select cast(message_body as nvarchar(MAX)) from [HelloWorldTargetQueue]
go

--step8
/*現在可以從目標隊列中接收消息並將響應發送回初始化程序。使用 Receive 命令可從隊列接收消息
*/
-- 聲明變量以存儲接收到的數據
SET NOCOUNT ON
DECLARE @conversationHandle uniqueidentifier --對話的標識符 
declare @message_body nvarchar(MAX)--消息體
declare @message_type_name sysname;--消息類型名稱

-- Service Broker 命令總是位於事務中
Begin Transaction;

-- Receive 命令的格式類似於一個選擇列表。首先列出要獲取的列,
-- 然后指定要從中獲取消息的隊列
RECEIVE top(1) -- 只接收一條消息,因此我們可以直接保存到變量中。
@message_type_name=message_type_name,  -- 接收的消息類型
@conversationHandle=conversation_handle, -- 對話的標識符,我們通過下列語句接收該消息
@message_body=message_body  -- 作為varbinary(MAX) blob 的消息內容
FROM [HelloWorldTargetQueue]

print @message_body

-- 如果這是一條 hello world 消息,則用相應的問候語回答
if @message_type_name = N'HelloWorldRequest'
Begin
SEND ON CONVERSATION @conversationHandle 
MESSAGE TYPE [HelloWorldResponse] 
(N'Hello From '+@@servername )

-- 這是我們希望從初始化程序接收的唯一消息,因此現在可以安全地結束對話。
END CONVERSATION @conversationHandle
End
-- 提交事務
-- 如果此時我們回滾,所有內容將退回到
-- 我們開始時的狀態 – 消息會返回到隊列,並且沒有發送響應
Commit
go

--step9
-- 確認我們從隊列中刪除了消息
select cast(message_body as nvarchar(MAX)) from [HelloWorldTargetQueue]
go

--step10
--響應已在對話中發送回初始化程序隊列,現在檢查響應是否成功到達:
select cast(message_body as nvarchar(MAX)) from [HelloWorldInitiatorQueue]
go

--step11
-- 最后接收並顯示響應消息:
RECEIVE  
cast(message_body as nvarchar(MAX))
FROM [HelloWorldInitiatorQueue]

執行上述代碼以后,我們可以查看SSMS中HelloWorldDB的Servic Broker屬性,如下圖所示,主要列出了我們創建的隊列、服務等信息:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM