日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

SQL Server 2005 Service Broker 初探

發(fā)布時間:2025/7/14 数据库 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SQL Server 2005 Service Broker 初探 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
發(fā)布日期 : 11/4/2004| 更新日期 : 11/4/2004

Roger Wolter

適用于:

Microsoft SQL Server 2005

Transact SQL (T-SQL) 語言

摘要:本文概述了如何利用 SQL Server 2005 中新增的 Service Broker 功能,加快并簡化基于異步排隊操作的 SQL Server 應(yīng)用程序的開發(fā)過程。(請注意,在示例文件中,程序員的注釋使用的是英文,本文中將其譯為中文是為了便于讀者理解。)

本頁內(nèi)容

引言
為什么排隊?wèi)?yīng)用程序難于編寫?
為什么要在數(shù)據(jù)庫中進(jìn)行消息傳送?
Service Broker 編程
Service Broker“Hello World”
示例
結(jié)論

引言

SQL Server 2005 的一個主要成就是可以實現(xiàn)可靠、可擴(kuò)展且功能完善的數(shù)據(jù)庫應(yīng)用程序。與 .NET Framework 2.0 公共語言運(yùn)行庫 (CLR) 的集成使開發(fā)人員可以將重要的業(yè)務(wù)邏輯與存儲過程合并,而 T-SQL 和 XML 中的新增功能擴(kuò)展了數(shù)據(jù)操作的可用范圍以及開發(fā)人員可用的存儲功能。另一個重要功能是 SQL Server Service Broker,它為數(shù)據(jù)庫應(yīng)用程序增加了可靠、可擴(kuò)展、分布式異步功能。

為什么要編寫異步排隊操作?

在開發(fā) SQL Server 2005 時,我們與成功開發(fā)過大型可擴(kuò)展數(shù)據(jù)庫應(yīng)用程序的人員進(jìn)行了交談。結(jié)果發(fā)現(xiàn)他們幾乎所有的應(yīng)用程序中都有一個或多個操作是以異步排隊方式執(zhí)行的。股票交易系統(tǒng)中的結(jié)算活動是排隊的,這樣可以在后臺進(jìn)行結(jié)算,在前端處理其他交易。訂單輸入系統(tǒng)中的發(fā)貨信息放在一個排隊中,稍后將由另一臺服務(wù)器(通常位于其他位置)上運(yùn)行的發(fā)貨系統(tǒng)讀取。旅行預(yù)訂系統(tǒng)在客戶填寫完路線后再進(jìn)行實際的預(yù)訂,并在預(yù)訂完成后發(fā)送確認(rèn)電子郵件。在所有這些示例中,許多工作都是通過異步方式完成的,從而提高了系統(tǒng)的響應(yīng)速度,因此用戶無須等待工作完成就可以收到響應(yīng)。

在大多數(shù)大型系統(tǒng)中,經(jīng)過仔細(xì)分析后都可以發(fā)現(xiàn),許多處理都可以通過異步方式完成。雖然應(yīng)用程序中的排隊任務(wù)無須立即完成,但系統(tǒng)必須確保這些任務(wù)能夠可靠地完成。Service Broker 使異步排隊任務(wù)的執(zhí)行可靠并且易于實現(xiàn)。

使應(yīng)用程序中的部分任務(wù)異步執(zhí)行的另一個優(yōu)勢是這些任務(wù)的處理工作可以在資源可用時完成。如果訂單輸入系統(tǒng)中的發(fā)貨任務(wù)可以從隊列中執(zhí)行,發(fā)貨系統(tǒng)就無需具有處理峰值訂單負(fù)載的能力。在許多訂單輸入系統(tǒng)中,峰值訂單率可能是平均訂單率的兩倍或三倍。由于訂單輸入系統(tǒng)必須具有處理峰值負(fù)載的能力,因此大量處理能力在很大一部分時間內(nèi)都處于閑置狀態(tài)。如果在出現(xiàn)峰值時對異步任務(wù)進(jìn)行排隊并在空閑時執(zhí)行,將顯著提高系統(tǒng)的利用率。

為什么排隊?wèi)?yīng)用程序難于編寫?

既然異步排隊?wèi)?yīng)用程序具有許多優(yōu)勢,為什么不以這種方式編寫所有應(yīng)用程序?這是因為編寫異步排隊?wèi)?yīng)用程序相當(dāng)困難!許多嘗試在應(yīng)用程序中使用數(shù)據(jù)庫表作為隊列的開發(fā)人員發(fā)現(xiàn),實際操作遠(yuǎn)比想象的困難。作為隊列的表中包含多個進(jìn)程,包括同時插入、讀取和刪除幾條記錄。這將帶來并發(fā)問題、降低系統(tǒng)性能并導(dǎo)致頻繁死機(jī)。盡管許多開發(fā)人員都成功地解決了這些難題,但實際操作卻非常困難。Service Broker 通過使隊列成為 SQL Server 2005 數(shù)據(jù)庫中的第一級數(shù)據(jù)庫對象解決了這些問題。編寫隊列的大多數(shù)難題都已解決,因此開發(fā)人員可以專注于編寫異步應(yīng)用程序,而不是編寫排隊基礎(chǔ)結(jié)構(gòu)。本文的其余內(nèi)容將討論編寫排隊?wèi)?yīng)用程序涉及到的難題,并解釋 Service Broker 如何幫助您解決這些難題。

消息的完整性

在許多異步排隊?wèi)?yīng)用程序中,排隊的消息實際上是有價值的業(yè)務(wù)對象。例如在訂單輸入系統(tǒng)中,如果將發(fā)貨信息放入隊列中以便稍后處理,那么丟失排隊的數(shù)據(jù)將意味著無法按訂單發(fā)貨。許多可靠的消息傳送系統(tǒng)都將消息存儲在文件系統(tǒng)中,因此磁盤驅(qū)動器的損壞將導(dǎo)致消息丟失。Service Broker 將消息存儲在隱藏的數(shù)據(jù)庫表中,因此 SQL Server 為保護(hù)數(shù)據(jù)而提供的所有數(shù)據(jù)完整性功能同樣可用于保護(hù)排隊的消息。如果使用數(shù)據(jù)庫鏡像進(jìn)行故障恢復(fù),當(dāng)因數(shù)據(jù)庫故障而轉(zhuǎn)移到第二個數(shù)據(jù)庫后,所有消息都會轉(zhuǎn)移到第二個數(shù)據(jù)庫中,這樣 Service Broker 應(yīng)用程序?qū)⒗^續(xù)運(yùn)行而不會丟失任何數(shù)據(jù)。

多讀取器隊列

多讀取器隊列是一種擴(kuò)展異步應(yīng)用程序的最有效的方式。為證明這一點,我將通過大家都熟悉的兩個示例說明如何進(jìn)行排隊。

在雜貨店排隊

大多數(shù)雜貨店都可以增設(shè)多個隊列。每個收銀臺都有其自己的隊列,因此要購買某些商品,您需要選擇一個隊列。如果您像我一樣,大多數(shù)時候選擇的隊列中都有一個滿載而歸的顧客排在您前面,他/她購買的很多商品都需要核實價格,而且要使用第三方遠(yuǎn)期支票進(jìn)行付款。在輪到您結(jié)帳之前,可能在您開始排隊時還沒有出門的顧客都已經(jīng)為他們購買的商品付完了款。這個例子說明了使用多個隊列時的一個問題:即,如果排在前面的任務(wù)需要很長時間才能處理完,后面的任務(wù)將無法得到及時處理。

使用多個隊列的另一個主要問題是,添加一個隊列后需要在各隊列之間重新分配任務(wù),在隊列之前來回移動任務(wù)可能會浪費(fèi)很多時間。還以上面的雜貨店為例,當(dāng)一個新的收銀臺開始工作時,想象一下許多顧客推著購物車蜂擁而至的場面吧。

在機(jī)場排隊

雖然航空公司并非高效率的典范,但大多數(shù)售票點的工作效率都比雜貨店要高,這是因為多個票務(wù)代理都在為一個隊列服務(wù)。由于只有一個隊列,因此您不必?fù)?dān)心排錯了隊。如果某個乘客占用了較長的時間,其他票務(wù)代理仍可以繼續(xù)為其他乘客服務(wù)(假定有多個票務(wù)代理)。

具有多個讀取器的一個隊列也可以輕松擴(kuò)展。如果隊列太長,可以增加代理而不必打斷隊列。某些代理也可以在接待完當(dāng)前乘客后離開,而不會在隊列中造成混亂。

盡管可能會偏離主題,但我們?nèi)砸詸C(jī)場隊列為例來說明基于隊列的應(yīng)用程序的另一個常見問題。假定排在一個隊列中的幾個人屬于一個團(tuán)隊,比如說,我和我的家人正在登記準(zhǔn)備去旅行。再假定我的家人由于到達(dá)時間不同而分散排在一個隊列中。如果我們希望坐在一起,那么代理將需要預(yù)留一排坐位。如果我和妻子同時來到不同的票務(wù)代理處,則我可能預(yù)訂了第 4 排的 5 個座位,而我的妻子預(yù)訂了第 47 排的 5 個座位。這是多讀取器隊列的一個主要問題:即,如果在不同的線程中同時處理相關(guān)的消息,將很難進(jìn)行協(xié)調(diào)。請想象一下同時處理訂單標(biāo)題和訂單內(nèi)容的情景。處理訂單內(nèi)容的讀取器會認(rèn)為沒有相關(guān)的訂單標(biāo)題,因為訂單標(biāo)題還未讀入數(shù)據(jù)庫。為了正確工作,訂單內(nèi)容必須多次重新查找訂單標(biāo)題,以確保訂單標(biāo)題只是被延遲而不是不存在。

一種更簡單的方法是讓第一個到達(dá)售票處的乘客將所有相關(guān)乘客都叫到前面來,以便由一個售票處為所有這些乘客提供服務(wù)。 Service Broker 的功能與此類似,它在接收到一條消息后鎖定相關(guān)的其他消息。持有鎖定的讀取器可以接收隊列中屬于同一組的所有其他消息,而其他讀取器都不能讀取這些消息。在提交事務(wù)之前,消息將一直保持鎖定狀態(tài)。該鎖定稱為“會話組”鎖定。會話組是開發(fā)人員定義的相關(guān)消息組。例如,處理特定訂單所需的所有對話(訂單標(biāo)題、訂單內(nèi)容、庫存、發(fā)貨、帳單等等)可能被放入同一個會話組中。從其中一個會話讀取消息時,將鎖定會話組中的其他消息,這樣只有持有鎖定的讀取器可以處理隊列中的所有相關(guān)消息。請注意,只鎖定一個組中的消息,這一點非常重要。盡管可以同時處理上百個組,但任一時刻一個線程只處理一個組。在提交或回滾線程創(chuàng)建的事務(wù)之前,組將一直處于鎖定狀態(tài)。

我想通過這個例子說明的最后一個問題是,當(dāng)持有會話組的事務(wù)被提交后,該會話組中的另一條消息到達(dá)時會發(fā)生什么情況。還以售票處為例,當(dāng)我的家人都登記后,我的一個孩子才到達(dá)機(jī)場。由于原始事務(wù)已經(jīng)結(jié)束,最后一位乘客可以由任一票務(wù)代理服務(wù)。只有在原始代理留下便條,說明該組中其他人員的位置時,新代理才能知道如何為最后一位乘客安排座位。同樣,當(dāng)處理相關(guān)消息組的事務(wù)完成時,必須記錄會話的“狀態(tài)”以便當(dāng)該組中下一條消息到達(dá)時,接收該消息的隊列讀取器了解上一個事務(wù)停止時的位置。因為這是數(shù)據(jù)庫應(yīng)用程序,所以存儲該狀態(tài)的位置應(yīng)該是一張數(shù)據(jù)庫表。Service Broker 提供了一個會話組 ID,可以使用它來方便地將會話狀態(tài)和會話中的消息相關(guān)聯(lián)。這是與會話組中每條消息一起顯示的唯一標(biāo)識符。如果唯一標(biāo)識符用作存儲狀態(tài)的表中的密鑰,則消息處理邏輯可以很容易地找到與接收到的每條消息相關(guān)聯(lián)的狀態(tài)。另外,因為每次只有一個隊列讀取器可以處理來自特定會話組的消息,所以開發(fā)人員不必?fù)?dān)心同時有兩個事務(wù)更新狀態(tài)行從而導(dǎo)致丟失狀態(tài)信息。

以上示例說明,多讀取器隊列是擴(kuò)展大型應(yīng)用程序的一種簡單而有效的方法。Service Broker 提供的會話組鎖定機(jī)制使編寫使用多讀取器隊列的應(yīng)用程序像編寫使用單讀取器隊列的應(yīng)用程序一樣容易。

分布

前面討論的隊列都假定位于一個數(shù)據(jù)庫中。為了開發(fā)適用于多種業(yè)務(wù)情況的松散耦合的分布式數(shù)據(jù)庫應(yīng)用程序,我們需要進(jìn)行擴(kuò)展,以包括分散在網(wǎng)絡(luò)中(通過可靠的消息傳送進(jìn)行通信)的多個數(shù)據(jù)庫中的隊列。我們需要可靠的消息傳送,因為如果使用數(shù)據(jù)庫確保隊列中消息的完整性,但消息卻在傳送到其他數(shù)據(jù)庫的過程中丟失,所有工作都將是徒勞的。

Service Broker 使用稱為“對話協(xié)議”的可靠消息傳送協(xié)議來確保發(fā)送到遠(yuǎn)程隊列的消息按順序到達(dá)并且僅到達(dá)一次。正如對話是雙向會話一樣,對話協(xié)議同時支持雙向的消息傳送。

對話消息具有標(biāo)題,可確保消息按正確順序安全地傳送到正確的目標(biāo)位置。它包含序列號、消息所在對話的標(biāo)識符、要發(fā)送到的服務(wù)的名稱、安全性信息以及用于控制消息傳送的一些其他信息。當(dāng)目標(biāo)位置成功接收到消息后,它將發(fā)出確認(rèn),以便源位置知道已成功傳送了消息。如果可能,確認(rèn)信息將包含在另一條消息的標(biāo)題中發(fā)送回源位置,以盡可能減小消息的數(shù)量。如果源位置在某一時限內(nèi)沒有收到確認(rèn),將重新發(fā)送該消息直到成功傳送。

消息傳送系統(tǒng)在傳送較大的消息時經(jīng)常會遇到問題。發(fā)送以 GB 為單位的消息會花幾分鐘時間,從而會占用一段時間的網(wǎng)絡(luò)連接。如果發(fā)生網(wǎng)絡(luò)錯誤導(dǎo)致重新發(fā)送消息多次,將會嚴(yán)重影響網(wǎng)絡(luò)性能。為了解決此問題,Service Broker 對話協(xié)議將大型消息拆分成多個較小的片段,然后再單獨發(fā)送每個片段。如果發(fā)生網(wǎng)絡(luò)錯誤導(dǎo)致重新發(fā)送,則只重新發(fā)送傳送失敗的消息片斷。因此,Service Broker 最大可以支持 2GB 的消息,而許多可靠的消息傳送系統(tǒng)只能發(fā)送 100MB 或更小的消息。

事務(wù)性消息傳送

“僅一次”消息處理需要使用事務(wù)性消息。為了說明此問題,假定某個應(yīng)用程序在處理消息的過程中發(fā)生了錯誤。當(dāng)應(yīng)用程序重新啟動時,它如何才能知道是否要處理發(fā)生錯誤時正在處理的消息呢?數(shù)據(jù)庫中可能已經(jīng)更新了消息處理的結(jié)果,因此重新處理消息可能產(chǎn)生重復(fù)的數(shù)據(jù)。唯一安全的處理方式是使接收消息成為更新數(shù)據(jù)庫的同一事務(wù)的一部分。在系統(tǒng)崩潰時數(shù)據(jù)庫更新和消息接收都回滾,因此數(shù)據(jù)庫和消息隊列的狀態(tài)與系統(tǒng)崩潰前的狀態(tài)相同。

因為所有 Service Broker 操作都在數(shù)據(jù)庫事務(wù)環(huán)境中發(fā)生,所以保證了消息傳送操作的 事務(wù)完整性。典型的 Service Broker 消息處理事務(wù)包括以下步驟:

  • 開始事務(wù)。

  • 從會話組中接收一條或多條消息。

  • 從狀態(tài)表中檢索會話的狀態(tài)。

  • 處理消息并根據(jù)消息內(nèi)容對應(yīng)用程序數(shù)據(jù)進(jìn)行一項或多項更新。

  • 發(fā)送一些 Service Broker 消息:即,將響應(yīng)發(fā)送到傳入的消息或?qū)⑾l(fā)送到處理傳入消息所需的其他服務(wù)。

  • 如果此會話組包含其他消息,則讀取和處理此會話組中的其他消息。

  • 使用新的會話狀態(tài)更新會話狀態(tài)表。

  • 提交事務(wù)

  • Service Broker 事務(wù)性消息傳送的一項重要功能是在任何時間如果崩潰或應(yīng)用程序發(fā)生錯誤,事務(wù)將回滾并且一切都返回到事務(wù)開始時的狀態(tài),即狀態(tài)不變、應(yīng)用程序數(shù)據(jù)不變、消息未發(fā)送并且接收的消息返回到隊列中。這使此類應(yīng)用程序中的錯誤處理非常簡單。

    隊列讀取器管理

    在 Service Broker 應(yīng)用程序的消息處理過程中,隊列讀取器首先從隊列接收消息。由于消息始終從隊列中拉出,因此在消息到達(dá)隊列時接收應(yīng)用程序必須正在運(yùn)行。許多異步消息應(yīng)用程序都面臨著一個問題,即如何確保隊列讀取器在需要時處于運(yùn)行狀態(tài)?有兩種傳統(tǒng)的方法:讓隊列讀取器成為連續(xù)運(yùn)行的服務(wù),或者使用觸發(fā)器,在每條消息到達(dá)時,都將觸發(fā)消息傳送系統(tǒng)。Windows NT 服務(wù)方法是指即使在不處理消息時也運(yùn)行應(yīng)用程序。由于隊列讀取器頻繁開始和停止,觸發(fā)器方法可能會遇到性能問題。

    Service Broker 采用稱為激活的中間狀態(tài)方法來管理隊列讀取器。為設(shè)置激活,DBA 將存儲過程與 Service Broker 隊列相關(guān)聯(lián)。當(dāng)?shù)谝粭l消息到達(dá)隊列時,激活邏輯將啟動指定的存儲過程。存儲過程負(fù)責(zé)接收和處理消息,直到隊列為空。隊列為空后,存儲過程可以終止以節(jié)省資源。

    如果 Service Broker 確定消息添加到隊列的速度比存儲過程能夠處理的速度快,激活邏輯將開始其他的存儲過程,直到存儲過程能夠處理傳入的消息或者達(dá)到了為隊列配置的存儲過程的最大數(shù)量。由于為隊列提供服務(wù)的隊列讀取器數(shù)量隨著傳入消息速率的更改增大或減小,因此所有時間都將運(yùn)行適當(dāng)數(shù)量的隊列讀取器。

    為什么要在數(shù)據(jù)庫中進(jìn)行消息傳送?

    關(guān)于 Service Broker 的一個常見問題是“為什么要將消息傳送功能內(nèi)置在數(shù)據(jù)庫中?數(shù)據(jù)庫外部難道沒有足夠可靠的消息傳送系統(tǒng)?”

    我希望前面的信息已經(jīng)說明了為什么要在數(shù)據(jù)庫引擎中內(nèi)置 Service Broker,下面提供了要在數(shù)據(jù)庫中傳送消息的一些其他理由:

    • 消息和數(shù)據(jù)的單客戶端連接。除了上一部分中提到的統(tǒng)一編程模型,還具有一些其他顯著的優(yōu)勢:

      • 當(dāng)在任何可以連接到數(shù)據(jù)庫的客戶端上運(yùn)行時,應(yīng)用程序可以通過事務(wù)接收消息。當(dāng)接收程序與隊列在同一計算機(jī)上運(yùn)行時,許多消息傳送系統(tǒng)只允許事務(wù)性接收。

      • 與在數(shù)據(jù)庫中不存儲消息的消息系統(tǒng)不同,事務(wù)性消息傳送不需要分布式事務(wù)或兩階段提交。

    • 數(shù)據(jù)和消息之間集成的管理、部署和操作。用于保護(hù)和管理數(shù)據(jù)庫數(shù)據(jù)的所有工具和技術(shù)同樣適用于消息:

      • 備份和恢復(fù)數(shù)據(jù)庫還可以備份和恢復(fù)消息隊列。

      • 如果使用群集或數(shù)據(jù)庫鏡像來保護(hù)數(shù)據(jù)庫以避免出現(xiàn)故障,則您的消息享有相同的保護(hù)。

      • 由于隊列具有相關(guān)的視圖,因此確定隊列中的操作非常簡單。要了解隊列中有多少條消息嗎?請從隊列中選擇 count(*)。要了解有多少條消息尚未傳送嗎?請從 sys.transmission_queue 中選擇 *。如果消息中包含 XML 數(shù)據(jù),則可以使用 XQuery 進(jìn)行搜索。可以使隊列中的消息與狀態(tài)信息甚至數(shù)據(jù)表相結(jié)合,以確定訂單輸入系統(tǒng)中特定訂單的完成狀態(tài)。

    • 將消息傳送功能內(nèi)置在數(shù)據(jù)庫中還有一些顯著的性能優(yōu)勢。

      • 正如前面所述,事務(wù)性消息不要求兩階段提交。

      • 消息更新、狀態(tài)更改和數(shù)據(jù)更新都記錄在同一事務(wù)日志中,因此在提交事務(wù)時只需寫入單個日志。

      • 可靠的消息傳送通常將消息從傳送隊列傳送到接收隊列。如果 Service Broker 檢測到接收隊列與傳送隊列位于同一數(shù)據(jù)庫實例中,則消息直接放入接收隊列中,從而節(jié)省了額外的輸入/輸出并減少了事務(wù)提交的次數(shù)。

    Service Broker 編程

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

    隊列

    Service Broker 使用隊列在消息發(fā)送程序和消息接收程序之間提供松散耦合。發(fā)送程序可以使用 SEND 命令將消息放到隊列中,然后應(yīng)用程序繼續(xù)操作并依靠 Service Broker 來確保消息到達(dá)其目標(biāo)位置。

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

    對話

    Service Broker 還實現(xiàn)了對話,對話是兩個端點之間的雙向消息流。對話中的所有消息都進(jìn)行了排序,而且對話消息總是按照發(fā)送的順序傳送。該順序在事務(wù)、輸入線程、輸出線程以及系統(tǒng)崩潰和重新啟動過程中都保持不變。有些消息系統(tǒng)可以確保單個事務(wù)中發(fā)送或接收的消息順序,但不能確保多個事務(wù)中的順序,因此 Service Broker 對話具有獨特的優(yōu)勢。

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

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

    消息類型

    當(dāng)前,所有 Service Broker 消息都與特定的消息類型相關(guān)聯(lián)。消息類型是與消息一起傳送的標(biāo)簽,因此接收消息的應(yīng)用程序可以確定所接收消息的類型。此外,如果消息包含 XML 文檔,則消息類型可以與 XML 架構(gòu)集合相關(guān)聯(lián)。如果為某個消息類型指定了架構(gòu)集合,則所接收的該類型消息將在收到時根據(jù)架構(gòu)集合進(jìn)行驗證,而沒有通過架構(gòu)驗證的消息將會被拒絕。

    規(guī)范

    Service Broker 規(guī)范是一個消息類型集合。一個對話總是與一個規(guī)范相關(guān)聯(lián),而規(guī)范定義哪些消息類型可以通過對話發(fā)送。

    服務(wù)

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

    Service Broker“Hello World”

    大多數(shù)編程語言書籍都以“Hello World”示例開始,因此我們也在 Service Broker 中使用 Hello World 作為示例。為簡化示例,我使用可以從 SQL Server Management Studio 查詢窗口運(yùn)行的 T-SQL 進(jìn)行編寫。大多數(shù) Service Broker 應(yīng)用程序?qū)⒆鳛槠胀ǖ臄?shù)據(jù)庫應(yīng)用程序,這些應(yīng)用程序由通過 ADO 或 ADO.NET 與數(shù)據(jù)庫進(jìn)行通信的可執(zhí)行程序和使用 T-SQL 或 .NET 語言編寫的 SQL Server 存儲過程構(gòu)成。

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

    -- 創(chuàng)建要使用的數(shù)據(jù)庫 Create Database HelloWorldDB go Use HelloWorldDB go -- 創(chuàng)建要使用的兩種消息類型。我們要使用的消息將是 -- 字符串而不是 XML - 因此無需進(jìn)行驗證 CREATE MESSAGE TYPE [HelloWorldRequest] VALIDATION = NONE CREATE MESSAGE TYPE [HelloWorldResponse] VALIDATION = NONE -- 創(chuàng)建一個限制此對話框中消息類型 -- 的規(guī)范。請求由對話框的初始化程序發(fā)出 -- 響應(yīng)消息由對話框目標(biāo)發(fā)送。 CREATE CONTRACT [HelloWorldContract]( [HelloWorldRequest] SENT BY initiator, [HelloWorldResponse] SENT BY target) -- 創(chuàng)建對話框在其間通信的兩個隊列。A -- 對話框請求兩個隊列。 CREATE QUEUE [HelloWorldTargetQueue] CREATE QUEUE [HelloWorldInitiatorQueue] -- 創(chuàng)建命名對話框端點的服務(wù)。服務(wù)會將 -- 會話端點連接到隊列。 CREATE SERVICE [HelloWorldRequestService] ON QUEUE [HelloWorldTargetQueue]( [HelloWorldContract] ) CREATE SERVICE [HelloWorldResponseService] ON QUEUE [HelloWorldInitiatorQueue] go

    現(xiàn)在已經(jīng)設(shè)置了元數(shù)據(jù),可以發(fā)送消息了。請注意,由于初始化程序和目標(biāo)服務(wù)位于同一 SQL Server 實例中,因此消息將直接轉(zhuǎn)到目標(biāo)隊列而不會通過傳送隊列傳送。由于 Service Broker 內(nèi)置在數(shù)據(jù)庫中,因此可以進(jìn)行此項性能優(yōu)化。

    Use HelloWorldDB goSET NOCOUNT ON DECLARE @conversationHandle uniqueidentifierBegin Transaction -- 開始 Hello World 服務(wù)的對話BEGIN DIALOG @conversationHandle FROM SERVICE [HelloWorldResponseService] TO SERVICE 'HelloWorldRequestService' ON CONTRACT [HelloWorldContract] WITH ENCRYPTION = OFF, LIFETIME = 600;-- 發(fā)送消息 SEND ON CONVERSATION @conversationHandle MESSAGE TYPE [HelloWorldRequest] (N'Hello World')commit

    讓我們查看目標(biāo)隊列以確保成功發(fā)送了消息。

    Use HelloWorldDB go-- 檢查目標(biāo)隊列以確認(rèn)消息已送達(dá) select * from [HelloWorldTargetQueue] go -- 將消息主體轉(zhuǎn)換為字符串,以便我們查看其中包含的內(nèi)容 select cast(message_body as nvarchar(MAX)) from [HelloWorldTargetQueue] go

    現(xiàn)在可以從目標(biāo)隊列中接收消息并將響應(yīng)發(fā)送回初始化程序。

    -- 使用 Receive 命令可從隊列接收消息-- 聲明變量以存儲接收到的數(shù)據(jù) SET NOCOUNT ON DECLARE @conversationHandle uniqueidentifier declare @message_body nvarchar(MAX) declare @message_type_name sysname;-- Service Broker 命令總是位于事務(wù)中 Begin Transaction;-- Receive 命令的格式類似于一個選擇列表。首先列出 -- 要獲取的列,然后指定要從中獲取消息 -- 的隊列 RECEIVE top(1) -- 只接收一條消息,因此我們可以直接保存到變量中。 @message_type_name=message_type_name, -- 接收的消息類型 @conversationHandle=conversation_handle, -- 對話的標(biāo)識符 -- 我們通過下列語句接收該消息 @message_body=message_body -- 作為 -- varbinary(MAX) blob 的消息內(nèi)容 FROM [HelloWorldTargetQueue]print @message_body-- 如果這是一條 hello world 消息,則用相應(yīng)的問候語回答 if @message_type_name = N'HelloWorldRequest' Begin SEND ON CONVERSATION @conversationHandle -- 使用下列消息接收語句的相同會話 MESSAGE TYPE [HelloWorldResponse] (N'Hello From '+@@servername ) -- 這是我們希望從初始化程序接收的唯一消息,因此 -- 現(xiàn)在可以安全地結(jié)束對話。 END CONVERSATION @conversationHandle End -- 提交事務(wù) -- 如果此時我們回滾,所有內(nèi)容將退回到 -- 我們開始時的狀態(tài) – 消息會返回到隊列,并且沒有發(fā)送響應(yīng) Commit go -- 確認(rèn)我們從隊列中刪除了消息 select cast(message_body as nvarchar(MAX)) from [HelloWorldTargetQueue] go

    響應(yīng)已在對話中發(fā)送回初始化程序隊列,現(xiàn)在檢查響應(yīng)是否成功到達(dá):

    Use HelloWorldDB goselect cast(message_body as nvarchar(MAX)) from [HelloWorldInitiatorQueue] go

    ... 最后接收并顯示響應(yīng)消息:

    RECEIVE cast(message_body as nvarchar(MAX)) FROM [HelloWorldInitiatorQueue]

    現(xiàn)在已經(jīng)成功地向 Service Broker 發(fā)送了消息并收到了響應(yīng)。如果希望查看剛剛運(yùn)行的命令的詳細(xì)說明,請參見 SQL Server 聯(lián)機(jī)書籍所提供的豐富消息。如果希望擴(kuò)展此示例以在兩個數(shù)據(jù)庫之間使用,您需要添加從發(fā)起程序服務(wù)器到目標(biāo)服務(wù)器的路由和從目標(biāo)返回到初始化程序的路由。Service Broker 路由將 BEGIN DIALOG CONVERSATION 命令中指定的服務(wù)名稱映射到發(fā)送消息所需的實際網(wǎng)絡(luò)地址信息。有關(guān)路由和安全性的詳細(xì)信息,請參見 SQL Server 聯(lián)機(jī)書籍。

    示例

    現(xiàn)在您已經(jīng)看到了 Service Broker 是如何工作的,下面將介紹可以使用 Service Broker 開發(fā)的部分應(yīng)用程序。

    訂單輸入

    許多程序都使用訂單輸入作為示例,因為大多數(shù)人都了解該過程。即使沒有開發(fā)過訂單輸入系統(tǒng)的開發(fā)人員至少都使用過訂單輸入系統(tǒng)進(jìn)行訂貨。

    基于 Service Broker 的訂單輸入系統(tǒng)使用隊列來將系統(tǒng)的子系統(tǒng)連接到一起。這不僅增加了并行度并且提高了效率,而且使配置和體系結(jié)構(gòu)具有非常大的靈活性。

    在本示例中,Service Broker 用于連接四個松散耦合的服務(wù)以處理每個訂單。在訂單輸入服務(wù)將訂單標(biāo)題和訂單內(nèi)容插入到數(shù)據(jù)庫中時,它根據(jù)計費(fèi)、發(fā)貨、庫存和信貸限額服務(wù)對消息進(jìn)行排隊以完成對訂單的處理。Service Broker 允許四項服務(wù)并行運(yùn)行,從而縮短了系統(tǒng)的響應(yīng)時間。

    根據(jù)系統(tǒng)的業(yè)務(wù)需求,訂單輸入服務(wù)可以等待收到所有四項服務(wù)的響應(yīng)后返回到用戶,也可以在提交初始事務(wù)后立即返回而在后臺執(zhí)行其余的服務(wù)。實現(xiàn)每個操作都會對訂單輸入服務(wù)進(jìn)行一些更改。每種情況中的其他服務(wù)保持不變。

    使用 Service Broker 鏈接服務(wù)還提供了幾個部署選項。所有五項服務(wù)可以在同一臺服務(wù)器上運(yùn)行,也可以根據(jù)需要分散在五臺服務(wù)器(在服務(wù)的負(fù)載平衡時可以為更多的服務(wù)器)上運(yùn)行以提供所需的效率。服務(wù)可以部署為存儲過程或外部應(yīng)用程序。這種靈活性對 ISV 非常有用,ISV 可以根據(jù)客戶對性能、冗余和效率的需求創(chuàng)建單個代碼庫并在各種配置中進(jìn)行部署。

    1 使用 Service Broker 鏈接五項訂單輸入和處理服務(wù)

    并行存儲過程

    最初發(fā)明觸發(fā)器時,數(shù)據(jù)庫公司通常對庫存表使用觸發(fā)器,在庫存量太低時自動發(fā)出訂單。雖然這是一個很好的概念,但是只有很少的系統(tǒng)使用了觸發(fā)器,因為在觸發(fā)器中執(zhí)行大段代碼的額外開銷會使數(shù)據(jù)庫的更新速度非常慢。Service Broker 允許觸發(fā)器對要完成的工作進(jìn)行排隊,以便觸發(fā)器可以完成和允許提交初始事務(wù),從而使這類應(yīng)用程序可以被廣泛采用。然后,排隊的工作在單獨的事務(wù)中完成,甚至可以在不同的數(shù)據(jù)庫中完成。SQL Server 2005 對“查詢通知”和“事件通知”使用此模型。

    Service Broker 還允許存儲過程并行開始幾個其他的存儲過程。此功能可以顯著縮短響應(yīng)時間。例如,某個呼叫中心應(yīng)用程序?qū)魅氲暮艚惺褂煤艚蟹?ID 查尋有關(guān)正在呼叫的客戶的所有信息,因此客戶服務(wù)代表可以獲取所有相關(guān)信息。在許多情況下,必須從不同系統(tǒng)上的不同數(shù)據(jù)庫中獲取這些信息。可以使用遠(yuǎn)程查詢獲取所有這些信息,但響應(yīng)時間可能太長。Service Broker 可以同步將請求排隊到所有遠(yuǎn)程服務(wù)并在其輸入隊列上等待結(jié)果。因為并行處理所有請求,所以總響應(yīng)時間將縮短。

    2 并行處理示例

    批處理

    批處理系統(tǒng)中經(jīng)常會使用 Service Broker 應(yīng)用程序。大多數(shù)批處理由許多小型的半獨立處理構(gòu)成,必須對這些半獨立處理進(jìn)行計劃和協(xié)調(diào)。獨立執(zhí)行子過程允許每個子系統(tǒng)按其最佳速度執(zhí)行,因此可以提高效率。

    在本示例中,將會不間斷地在輸入隊列上累計對批計劃過程的輸入,包括預(yù)購、預(yù)測、返回等等。當(dāng)計劃引擎運(yùn)行時,它閱讀隊列中的輸入、進(jìn)行分析、然后將請求排隊到處理計劃輸出的子過程。輸出隊列允許在一臺服務(wù)器或多臺服務(wù)器上并行地單獨執(zhí)行子過程。這允許根據(jù)需要擴(kuò)展任意多臺服務(wù)器以滿足處理負(fù)載的需求。

    圖 3:大批量處理示例

    旅行預(yù)訂

    以前,我經(jīng)常為碩士研究生講授分布式數(shù)據(jù)庫類。我曾經(jīng)使用的一個分布式事務(wù)的示例是旅行社在同一事務(wù)中預(yù)訂了飛機(jī)票、旅館房間和租車服務(wù),因為客戶在無法進(jìn)行航空旅行時不會預(yù)訂旅館。像許多示例一樣,直到有一天一位來自真正旅行社的程序員來到了教室里,我們才了解真實的情況。他告訴我真正的旅行社不是這樣工作的。在預(yù)訂旅館房間時,航空公司不允許任何人鎖定其預(yù)訂表格和座位安排。預(yù)訂根據(jù)當(dāng)前的可用性完成,并且如果在實施預(yù)訂時已經(jīng)沒有空余的座位或房間,將給客戶打電話以確保新的預(yù)訂滿足客戶需求。

    在旅行預(yù)訂 Web 站點示例中,預(yù)訂根據(jù)有關(guān)航空公司和旅店可用性的數(shù)據(jù)表來完成。這些表包含來自航空公司或旅館的信息。信息會經(jīng)常更新,但總是會有一點過時。實際的預(yù)訂在客戶預(yù)約旅行后才發(fā)生,并可能在客戶取消旅行后被取消。

    這種延遲的活動非常適合 Service Broker 體系結(jié)構(gòu)。記錄客戶旅行安排的事務(wù)將消息提交到進(jìn)行實際預(yù)訂的后端服務(wù)。預(yù)訂服務(wù)讀取隊列中的消息并在單獨的事務(wù)中處理每個預(yù)訂。預(yù)訂服務(wù)通過各種協(xié)議與預(yù)訂航空公司和旅館服務(wù)的系統(tǒng)進(jìn)行通信。這些通信可能包括 Web 服務(wù)、SNA、HTTP、EDI、傳真、Service Broker 等等。由于對到預(yù)訂服務(wù)的輸入進(jìn)行了排隊,因此這些協(xié)議的不同滯后時間不會帶來問題。如果隊列太長,Service Broker 激活可以啟動更多的隊列讀取器來處理負(fù)載。如果負(fù)載達(dá)到預(yù)訂服務(wù)器能夠處理的最大值,則可以通過向路由表添加行來添加更多的服務(wù)器。

    在成功完成特定路線的所有預(yù)訂后,會將一條消息排隊到 SQLiMail 服務(wù)器以向客戶發(fā)送確認(rèn)電子郵件。如果一項或多項預(yù)訂未能完成,將通知客戶服務(wù)代表來幫助重新預(yù)訂旅行。

    “處理更新”服務(wù)在后臺運(yùn)行,并定期從旅館和航空公司接收可用性信息。這些信息被轉(zhuǎn)換為常見的 XML 格式,然后通過通知服務(wù)發(fā)布到 Web 集群中的服務(wù)器以更新旅館和航空公司的可用性表。

    松散耦合的 Service Broker 體系結(jié)構(gòu)允許通過加載軟件、配置數(shù)據(jù)庫和訂閱可用性反饋來將 Web 服務(wù)器添加到服務(wù)器集群。可以編寫腳本以使進(jìn)行操作時只需最少的手動干預(yù)。為向預(yù)訂服務(wù)添加更多后端服務(wù)器,必須安裝和配置該服務(wù),然后必須將新的服務(wù)器地址添加到 Web 服務(wù)器中的路由表。

    4 旅行預(yù)訂示例 ?

    結(jié)論

    SQL Server 2005 Service Broker 是用于生成分布式異步數(shù)據(jù)庫應(yīng)用程序的新平臺。SQL Server 數(shù)據(jù)庫中包括的可靠異步消息功能使您可以生成各種以前難以生成甚至無法生成的數(shù)據(jù)庫應(yīng)用程序。SQL Server 2005 集成了 Service Broker 以及 CLR 和 XML 數(shù)據(jù)類型等其他開發(fā)人員功能,成為生成高度可擴(kuò)展數(shù)據(jù)庫應(yīng)用程序的一個主要平臺。

    轉(zhuǎn)載于:https://www.cnblogs.com/Tim-Yi/archive/2011/10/15/2212760.html

    總結(jié)

    以上是生活随笔為你收集整理的SQL Server 2005 Service Broker 初探的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。