1

目標:継続的に生成されたレコードを中央SQLに確実に転送します。

要約:衛星は中央にその側の最新のデータは何かを尋ねる必要があり、それからそれは継続的に新しいデータを送信する予定です。

サテライトSQLサーバーは(物理的な実稼働マシンに関連して)時々(再)起動される場合があり、中央のSQLマシンはより長く実行される可能性がありますが、ダウンタイムも発生する可能性があります。回線はほとんど信頼できますが、誰にもわかりません...接続の問題はSQL ServerServiceBrokerによって自然に解決されると思います。ただし、最初のハンドシェイクとデータ送信の問題を解決する必要があります。プロトコルを設計する必要がありますが、SSBの知識はまだ不十分です。

SSBを使用したコミュニケーションの基本を理解していただければ幸いです。

各作業項目は、それぞれの会話から始める必要があります。プロデューサー(イニシエーター)はダイアログを開始し、作業項目を説明するメッセージを送信してから、コミットします。コンシューマー(ターゲット)はメッセージを受信し(またはアクティブ化され)、ペイロードを検査して作業項目の詳細を理解し、作業を実行してから、ダイアログを終了してコミットします。結果のEndDialogメッセージはイニシエーターサービスキューに返送され、イニシエーターキューでアクティブ化されたプロシージャは、イニシエーター側のダイアログを終了することでそれに応答します。

... Remus Rusanuによる(興味がある場合は、彼の以前の回答で詳細を参照してください)。

このような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" />

そして、XMLメッセージから情報を取得するためのの書き方SELECTをすでに学びました。

通信: SQLサーバー間の通信メカニズムがアクティブ化されたとしましょう...

  1. サテライトSQLは新しいデータを取得しましたが、どういうわけか、サテライトとセントラルの間に保留中のメッセージがないことを認識しています。ただし、どのデータがすでにセントラルに送信されているかもわかりません。したがって、中央に最後に利用可能なデータは何かを尋ねる必要があります。

  2. 私がEND CONVERSATION正しく理解していれば、このコマンドは一種の空のメッセージのみを送信しますN'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'。このため、セントラルはおそらく、のReplyMessage前に回答を含む私のタイプを送信する必要がありEND CONVERSATIONます。

  3. その間、衛星はおそらく非同期で動作するために何もしないはずです(つまり、送信後に待機しますRequestMessage)。ReplyMessage到着すると、次のような衛星手順がアクティブになります。

    • メッセージを受信し、必要な情報を取得し、
    • EndDialogメッセージを受信し、衛星側で前のダイアログを終了します。
    • セントラル(XML文字列形式)に送信するデータを準備します。
    • 新しいダイアログを開き、
    • 準備されたデータを送信し、
    • ReplyMessage別の人が到着するまで休眠状態になります。
  4. セントラルも同様に動作する必要があります。RequestMessage到着すると、次のような中央手順がアクティブになります。

    • リクエストメッセージを受信し、
    • XML情報を抽出し、中央データベースを更新します。
    • 衛星で利用可能な最後のデータに関する情報を取得し、
    • を形成して送信しReplyMessageます
    • 中央側でダイアログを終了します。

これまでのところ、私の見解は正しいですか?

さて、私にはよくわからない詳細がいくつかあります。人の手を触れずに動作する堅牢なものにしたいので、メカニズムがインストールされたときに自動的に起動する必要があります。通信は常に衛星によって開始されるべきです(衛星が機能している、あるいは存在しているとしても、中央は知らないかもしれません)。

衛星は、中央で収集されるレコードを構築するために処理される生データによって起動されるトリガーをすでに使用しています。このようにして、トリガーはどういうわけか中央への衛星の最初のSSB要求を開始することができます。だが...

  • トリガーは、衛星と中央の間に保留中の通信がないことをどのように確認できますか?衛星は常にイニシエーターであるため、質問は次のように定式化することもできます...トリガーは、衛星が何らかの待機をしているかどうかをどのように確認できますかReplyMessage?または、衛星と中央衛星の間に開いたダイアログがあることを知る方法はありますか?
    • 会話がない場合、トリガーはデータレコード(ローカルテーブルに格納されている)を形成し、通信プロセスを開始できます(上記のポイント1を参照)。
    • 会話がある場合、トリガーは後で送信されるレコードのみを形成し、他には何も行われません。データはReplyMessage、アクティブ化された手順によって取得されたときに送信されます(上記のポイント3を参照)。
  • サテライトを休止状態にすると(上記のポイント3の最後の箇条書きを参照)、メッセージキューに他のメッセージがない可能性があり(ループで処理されるものがない)、アクティブ化された手順が自然に終了することを意味します。しかし、ここで正しく考えているかどうかはわかりません。コメントしてもらえますか?
  • 何も壊れておらず、データが十分に速く生成されている場合、衛星と中央衛星は常に何かを交換する必要があります。このように、トリガーは通信を開始しようとしないでください。
  • アクティブ化された衛星手順によってセントラルに送信されるものが他にない場合(実際にはアクティブではありません)、またはシステムが何らかの方法で再起動された場合(ダイアログがまだ存在しない場合)、トリガーは通信プロセスを開始します。しかし、どうすればそれを行うことができますか?トリガーは単にRequestMessage中央に送信する必要がありますか?(このようにするReplyMessageと、衛星手順がアクティブになり、処理するものができるまで手順が続行されます。)
  • たとえば、ここでのRequestMessage手段はいくつかのデータであり、それらを処理し、最後のものを返信します(または、次に送信する必要があるもの、または中央から推奨される次のアクションは、ビジネスロジックによって異なりますが、ここではおそらく重要ではありません)。他に何が必要かわからないという意味で、空のXMLを送信しても大丈夫ですか?教えてください。RequestMessage

最初の更新-以下のRemusRusanuの回答に基づいています。

これがおしゃべりなプロトコルになることに同意する必要があります。さらに、レコードは実際の環境からの温度サンプルとして作成され、サンプリングの頻度はかなり低くなります。これは、複雑なプロトコルは、すべてを再起動するという特別な場合にのみ役立つ可能性があることを意味します。

ただし、会話を永久に開いたままにしておく必要がある場合は、ダイアログハンドルの一意の識別子を保持するか、構成テーブルに永続的に保存する必要があります。または、コードにハードワイヤードすることもできます。トリガーはその場でレコードをすぐに送信し、セントラルは単にを送信しませんReplyMessage。それが正しいか?そのような報道は、事実上独白と見なすことができますか?

この質問を適度に短くするための2番目の更新。

継続サービスブローカーを参照してください:トリガーは、無限に開いたダイアログをどのように開始する必要がありますか?

4

1 に答える 1

2

最初のハンドシェイクとデータ送信の問題を解決する必要があります。

これを読んだことで2004年のフラッシュメモリがどのように復活したかはわかりません...当時、私たちはデザインのパブリッシュ/サブスクライブプロトコル(「モノローグ」と「ダイアログ」)を使用しており、デザインポイントの1つは「」の要件でした。チェックポイント」。このように考えてください。「発行者」はアイテムのカタログを配布します。最初にカタログのコンテンツをチェックポイントメッセージとして送信し、次にカタログへの更新(追加または削除されたアイテム、価格変更など)を更新として送信し続けます。メッセージ。誰かがこの出版物を購読するときはいつでも、彼のカタログが最新になるように、チェックポイントメッセージとその後のすべての更新メッセージを受け取る必要があります。やがて更新のリストが非常に長くなるため、発行者は定期的に現在のカタログの状態を「チェックポイント」として再送信します。後続のサブスクライバーには、最後のチェックポイントとそれ以降の更新のみが必要です。また、パブリッシャーインフラストラクチャは、サブスクライバーがそれを必要としないため、その最後のチェックポイントの前に送信されたすべてのメッセージを削除できます。これにより、新しいサブスクライバーがデータストリームの「途中」に参加し、一貫した状態を取得するという問題が解決されます。問題(および解決策)は、SQL Server自体がログ記録と回復を処理する方法と同じです(「チェックポイント」という名前は偶然ではありません...)。もちろん、

提案されたメッセージ交換パターンを次のように要約します。衛星は中央ステーションにセンターの現在のステータス(「透かし」)について尋ねる必要があります。これは、一般的な要求/応答パターンで行われます。送信者側ではBEGIN_TRAN-> BEGIN_DIALOG-> SEND_Request-> COMMIT、受信側ではActivation-> BEGIN_TRAN-> RECEIVE-> SEND_Response-> END-> COMMIT、Activation->BEGIN_TRANです。 -> RECEIVE->END->COMMIT送信側。

これは一般的にはOKのパターンですが、あなたが望むパターンではないと思います。最終的には次のようになります。サテライトが持っている新しい情報ごとに、センターに「これはもう持っていますか?」と尋ねられます。その後、センターは「ええ、はい、そうします」または「いいえ、送ってください」と応答します。。これは信じられないほどおしゃべりなプロトコルであり、最終的にはサテライトからセンターに至るすべての情報に対して多くのメッセージが交換されます。会話を長く開いたままにして、コミュニケーションチャネルと考えるべきだと思います。確立されると、サテライトは新しい情報を取得するたびにデータを送信するだけです。センターのステータスを尋ねる必要はありません。ネットワーク障害が発生した場合でも、送信したものがすべてセンターに到着するようにするためのSSBジョブです。会話を開始し、1MMメッセージを送信して開いたままにしておくことは、SSBプログラミングではまったく問題ありません。したがって、3か月後にさらに1MMメッセージを送信します。また、システムが2週間切断されていて、感謝祭の後でしか実際にメッセージを配信できない場合でも、そうすることができます。あれはSSBが処理するように設計されているものとまったく同じです。落とし穴は、プログラムコードもこれを処理できるように準備する必要があるということです(つまり、応答を待つことはありません。2週間以内に届く可能性があります)。

SSBプログラミングモデルについてもう少し説明します。通常、誰かが何かを積極的に「待っている」場所はどこにもありません。SSBプログラミングは、すべてイベントに応答することです。アクティベーションモデルは、現在の「関数型プログラミング」に非常に近いものです。node.jsを考えてください。コードの大部分は、アクティブ化されたプロシージャに依存します。コードは常に次の形式である必要があります'トランザクションの開始->メッセージの受信->メッセージに関連するアイテムのDBからの現在の状態の読み取り->結果の決定->データベースの状態の更新->応答の送信(存在する場合)->コミット- >終了します。onyl例外は、トリガーのようなものです。つまり、アクティベーション駆動型プロシージャのこのピンポンに新しいメッセージを挿入するコードです。このコード(トリガー)は、送信されたものが何であれ、応答を待つことはありません。送信して続行する必要があります。このトリガーのSENDに対する応答は、アクティベーションによって処理する必要があります。非同期で、再び。C#の新しいawaitasyncを考えてみてください。

于 2012-11-02T15:55:48.987 に答える