2012-11-02 54 views
1

目標:將連續生成的記錄可靠地傳輸到中央SQL。服務代理:設計兩臺SQL服務器之間的通信

摘要:衛星需要詢問中央站的最新數據是什麼,然後它會發送不斷更新的數據。

衛星SQL服務器有時可能(重新)啓動(與physicall生產機器有關),中央SQL機器可能運行更長時間,但也可能會有一些停機時間。這些線路大部分是可靠的,但從來不知道......我希望SQL Server Service Broker自然地解決連接問題。但是,我需要解決初始握手和發送數據的問題。我需要設計協議,我的SSB知識仍然很差。

我希望我使用SSB是很好的,並簡要描述爲

你應該對自己的談話每項工作開始瞭解溝通的基本知識。生產者(發起者)開始對話併發送描述工作項目的消息,然後提交。消費者(目標)接收消息(或被激活),檢查有效負載以瞭解工作項目詳細信息,執行工作,然後結束對話並提交。得到的EndDialog消息被髮送回發起者服務隊列,並且發起者隊列上的激活過程通過結束髮起者側的對話來響應它。

...通過Remus Rusanu(如果感興趣,請參閱more details in his earlier answer)。

我想(在這裏一個多字符串)發送記錄,因爲像這樣的XML消息

<row a="1" b="11" c="111" /> 
<row a="2" b="22" c="222" /> 
<row a="3" b="33" c="333" /> 
<row a="4" b="44" c="444" /> 

,我已經學會了how to write the SELECT to obtain the info from the XML message

通信:說出SQL服務器之間的通信機制,只是激活...

  1. 衛星SQL獲得的新數據,並不知它知道有衛星之間沒有懸而未決的消息和中央。但它也不知道什麼數據已經發送到中央。因此它必須詢問中央最後可用的數據是什麼。

  2. 如果我正確理解了END CONVERSATION,則該命令會導致僅發送一種空消息N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'。因此,中央應該在END CONVERSATION之前發回我的類型ReplyMessage

  3. 同時,衛星應該不會異步表現(即在發送RequestMessage之後等待)。一旦ReplyMessage到達時,它會激活衛星的過程是:

    • 接收到該消息,並得到想要的信息,
    • 接收的EndDialog消息,並結束於衛星側先前的對話框,
    • 準備數據要被髮送到所述中央(XML字符串形式),
    • 打開新的對話框,
    • 發送準備的數據,
    • 並且使本身休眠狀態,直到另一個ReplyMessage到達。
  4. 中央應該表現相似。一旦RequestMessage到達時,它會激活中心的過程:

    • 接收請求消息,
    • 提取XML信息並更新中央數據庫,
    • 得到有關衛星的最後一個可用的數據信息,
    • 表格併發送ReplyMessage,
    • 結束中央側的對話框。

到目前爲止,我的觀點是否正確?

現在我不確定一些細節:因爲我想讓它強健,沒有人情味,它應該在安裝機制時自行啓動。通信應始終由衛星啓動(即使衛星工作或甚至存在,中央可能也不知道)。

衛星已經使用由原始數據觸發的觸發器,該數據被處理來構建在中央收集的記錄。這樣,觸發器可以以某種方式啓動衛星對中心的第一個SSB請求。但是...

  • 觸發器如何檢查衛星和中心之間沒有未決通信?由於衛星始終是發起者,因此問題也可以表述爲......觸發器如何檢查衛星是否等待某個ReplyMessage?或者,如何知道衛星和中央之間有一些公開的對話?
    • 如果沒有對話,則觸發器形成數據記錄(存儲在本地表中),然後它可以啓動通信過程(參見上面的第1點)。
    • 如果有任何對話,觸發器只會形成稍後要發送的記錄,並且不做其他任何事情。當通過激活的程序獲得ReplyMessage時,將發送數據(參見上面的第3點)。
  • 使衛星休眠(見點上方3的最後一顆子彈),我的意思是,應該有可能是在消息隊列中沒有其他消息(沒有在環中處理的)和被激活程序自然完成。但我不確定這是否正確。你能評論一下嗎?
  • 如果沒有任何事情被破壞,並且數據產生得足夠快,衛星和中央總是有交換的東西。這樣,觸發器就不應該嘗試開始通信。
  • 當被激活的衛星程序沒有其他東西被髮送到中央(實際上,它不是活動的),或者當系統以某種方式重新啓動時(沒有對話存在),觸發器開始通信過程。但我怎麼能這樣做?觸發器是否應該將RequestMessage發送到中央? (這樣的ReplyMessage會激活衛星的過程和程序將繼續下去,直到有什麼事情要處理。)
  • 說了,RequestMessage意味着這裏是一些數據,對它們進行處理,並回復什麼是最後(或什麼接下來應該發送或者從中央推薦下一個動作 - 取決於業務邏輯,這裏可能不重要)。是否可以發送空的XMLRequestMessage的意義上我不知道你還需要什麼 - 告訴我

首先更新 - 基於the Remus Rusanu's answer below

我必須同意這將是chatty協議。此外,記錄是作爲來自真實環境的溫度樣本創建的,並且採樣頻率很低。這意味着複雜的協議只有在重啓所有東西的特殊情況下才有用。

但是,當對話應該保持開放永遠,對話框句柄的唯一標識符或應該永久存儲在某個配置表中,或者甚至可以硬連接到代碼。觸發器將立即發送記錄,中央將不會發送ReplyMessage。這是對的嗎?這種覆蓋能否被有效地視爲一種獨白?

第二次更新使這個問題合理簡短。

見延續Service Broker: How should a trigger start infinitely opened dialog?

回答

2

我需要解決的初始握手的問題,併發送數據。

我不能告訴你如何讀取這從2004年帶回閃存......當時我們在設計發佈 - 訂閱協議('monologs'與'對話框')和設計點之一是「檢查站」的要求。這樣思考:'發佈者'分發一個項目目錄。它最初將目錄的內容作爲檢查點消息發送,然後它繼續向目錄發送任何更新(增加或刪除的項目,價格變化等),作爲更新消息。每當有人訂閱本刊物時,它需要獲取檢查點消息和所有後續更新消息,以便他的目錄是最新的。隨着時間的推移,更新列表變得過長,因此定期發佈者將當前目錄狀態重新發送爲「檢查點」。隨後的用戶只需要最後一個檢查點,以及從那之後的任何更新。此外,發佈者基礎結構可以刪除在最後一個檢查點之前發送的所有消息,因爲沒有用戶會再需要它。這解決了新用戶加入數據流「中間」並獲得一致狀態的問題。問題(和解決方案)與SQL Server本身如何處理日誌記錄和恢復(以及名稱「檢查點」不是巧合......)沒有什麼不同。當然,現在整個pub-sub實現最終都是封閉的,你所擁有的只是對話框,它們不能提供實現我所描述的「開箱即用」的手段,這就是爲什麼我看到你在嘗試自己發明替代品......但我離題了。

我會總結一下你提出的消息交換模式:衛星需要詢問中心站有關中心的當前狀態('水印')。它在典型的請求 - 響應模式下執行:BEGIN_TRAN-> BEGIN_DIALOG-> SEND_Request-> COMMIT在發送方,Activation-> BEGIN_TRAN-> RECEIVE-> SEND_Response-> END-> COMMIT在接收方大小上,Activation-> BEGIN_TRAN - > RECEIVE-> END->發送方的COMMIT。

這是一般模式,但我不認爲是你想要的模式。你最終得到的是這樣的:對於衛星有的每一條新信息,它都會問中心:「你有這個嗎?」然後中心會迴應'嗯,是的,我'或'不,請寄給我'。這是一個令人難以置信的聊天協議,涉及大量的消息被交換爲每一個信息,最終使它從衛星到中心。我認爲你應該長時間保持對話,將它們視爲溝通渠道。一旦建立,衛星將每次發送數據時每次都有新的信息。你不需要詢問中心的地位,SSB的工作是確保你發送的任何東西到達中心,即使在網絡出現故障時也是如此。開始對話,發送一條1MM消息並保持打開狀態是完全可以在SSB編程中完成。所以3個月後再發送1MM郵件。甚至在系統斷開連續2周的情況下這樣做,只能在感恩節之後實際傳遞消息。那是究竟是什麼SSB被設計來處理。問題是你的程序代碼也應該準備好處理這個問題(即不要等待回覆,它可能會在2周內進入)。

關於SSB編程模型的更多詞語。通常情況下,任何時候都沒有人積極「等待」任何事情,SSB編程就是要回應事件。激活模型更接近現在的'函數式編程'。認爲node.js.絕大多數代碼將依賴於激活的過程。您的代碼應始終採用「begin transaction - > receive message->從數據庫讀取消息所屬項目的當前狀態 - >決定結果 - >更新db狀態 - >發送響應(如果有) - > commit- >退出。 onyl例外情況就像觸發器一樣,也就是在這個激活驅動程序的乒乓中注入新消息的代碼。這個代碼(觸發器)永遠不會等待任何發送的響應。它應該發送並繼續。對此觸發器的SEND的任何響應應通過激活來處理。異步,再次。想想C#的新異步。

+0

謝謝!一般來說,我知道由事件控制的異步通信。請查看更新後的問題,並可能需要繼續參考。 – pepr