6

Sql Server Service Brokerの外部アクティベーションメカニズム(FeaturePackのServiceBroker External Activatorを介して)を使用する実際の本番アプリケーションを展開した人からのガイダンスが必要です。

現在の考え方:

私のスペックはかなり単純です(または少なくとも私はそう思います)ので、私は次の基本的なフローを考えています:

  1. 注文のようなエンティティは、状態が「確認済み」のTable_Ordersに挿入されます

  2. SP_BeginOrderが実行され、次のことを行います。

    • トランザクションを開始します
    • Service_HandleOrderStateからService_PreprocessOrderへのDIALOGを開始します
    • 会話ハンドル(今後はPreprocessingHandle )をOrdersテーブル の特定の列に格納します
    • PreprocessingHandleを使用して、注文IDを含むタイプMessage_PreprocessOrderのMESSAGEを送信します
    • トランザクションを終了します

    私は会話を終わらせないことに注意してください、私は「ファイアアンドフォーゲット」を望んでいません

  3. Queue_PreprocessOrderのイベント通知は、次のことを行うPreprocessOrder.exeのインスタンス(最大同時実行数は1)をアクティブにします。

    • SqlTransactionを開始します
    • Queue_PreprocessOrderから上位1つのMESSAGEを受け取ります
    • メッセージタイプがMessage_PreprocessOrder(フォーマットXML)の場合:
      • メッセージ本文の注文IDを使用して、 Table_Ordersで注文状態を「前処理」に設定します
      • n個のカルテシアン積を計算するデータのn個のコレクションをロードし(Linqを介して、これはT-SQLでは不可能です)、注文アイテムのコレクションを決定します
      • 注文アイテムの行をTable_OrderItemsに挿入します
      • PreprocessingHandleを使用して、同じ注文IDを含むタイプMessage_PreprocessingDoneのMESSAGEを送信します
      • PreprocessingHandleに関連する会話を終了します
    • SqlTransactionをコミットします
    • Environment.Exit(0)で終了します
  4. Queue_HandleOrderStateの内部アクティベーションは、次のようなSP(最大同時実行数1)を実行します。
    • トランザクションを開始します
    • Queue_InitiatePreprocessOrderからトップ1のメッセージを受け取ります
    • メッセージタイプがMessage_PreprocessingDoneの場合:
      • メッセージ本文の注文IDを使用して、 Table_Ordersで注文状態を「処理中」に設定します
      • Service_HandleOrderStateからService_ProcessOrderItemへのDIALOGを開始します
      • 会話ハンドル(今後はProcessOrderItemsHandle)をTable_Ordersの特定の列に格納します
      • Table_OrderItemsの現在の注文IDと 各行の行にカーソルを作成します。
        • ProcessOrderItemsHandleを使用して、注文アイテムIDを含むタイプMessage_ProcessOrderItemのMESSAGEを送信します
    • メッセージタイプがMessage_ProcessingDoneの場合:
      • メッセージ本文の注文IDを使用して、 Table_Ordersで注文状態を「処理済み」に設定します
    • メッセージタイプがhttp://schemas.microsoft.com/SQL/ServiceBroker/EndDialog(END DIALOG)の場合:
      • メッセージの会話ハンドルに関連する会話を終了します
    • トランザクションを終了します
  5. Queue_ProcessOrderItemのイベント通知は、次のことを行うProcessOrderItem.exeのインスタンス(最大同時実行数は1)をアクティブにします。
    • SqlTransactionを開始します
    • Queue_ProcessOrderItemから上位1つのMESSAGEを受け取ります
    • メッセージタイプがMessage_ProcessOrderItem(フォーマットXML)の場合:
      • メッセージ本文の注文アイテムIDを使用して 、 Table_OrdersItemsで注文アイテムの状態を「処理中」に設定します。
        • 注文アイテムパラメータのコレクションをロードします
        • パラメータを使用してURLにHttpRequestを作成します
        • HttpResponseをPDFとしてファイルシステムに保存します
      • 上記のサブステップでエラーが発生した場合は、注文アイテムの状態を「エラー」に設定します。それ以外の場合は「OK」に設定します。
      • Table_OrdersItemsでルックアップを実行して、すべての注文アイテムが処理されているかどうかを判断します(状態は「ok」または「error」)
      • すべての注文アイテムが処理される場合:
        • ProcessOrderItemsHandleを使用して、注文IDを含むタイプMessage_ProcessingDoneのMESSAGEを送信します
        • ProcessOrderItemsHandleに関連する会話を終了します
    • SqlTransactionをコミットします
    • Environment.Exit(0)で終了します

ノート:

  • 仕様では、2005年から2012年までのMSSQL互換性を指定しているため、次のようになります。
    • 会話グループなし
    • 会話の優先順位はありません
    • POISON_MESSAGE_HANDLINGなし(ステータス=オフ)
  • 私は速度ではなく、全体的な流れの完全性と連続性を達成するために努力しています
  • テーブルとSPがDB1に存在し、Service Brokerオブジェクト(メッセージ、コントラクト、キュー、サービス)がDB2に存在する場合DB2は信頼できるものになります。

質問:

  1. 説明されているアーキテクチャに大きな設計上の欠陥はありますか?
  2. 注文完了状態の追跡が正しくないようです。より良い方法はありますか?たぶんQUEUERETENTIONを使用していますか?
  3. 私の直感によると、アクティブ化された外部exeが0以外の終了コードで終了することは決してないのでtry{..}catch(Exception e){..} finally{ Environment.Exit(0) }、Mainにあるはずです。この仮定は正しいですか?
  4. DBコードでエラー処理をどのように整理しますか?エラーログテーブルで十分ですか?
  5. 外部exeC#コードでエラー処理をどのように整理しますか?同じエラーログテーブル?
  6. SQL Server Service Brokerの製品サンプルを見てきましたが、Service Broker Interfaceは、一見単純なケースではやり過ぎのようです。より単純なServiceBrokerオブジェクトモデルの代替手段はありますか?
  7. 少なくとも毒メッセージを排出できるServiceBroker用のクロスバージョンの「ポータブル」管理ツールはありますか?
  8. 上記のいずれかの適切なコードサンプルはありますか?
4

1 に答える 1

3

Q:説明されているアーキテクチャに大きな設計上の欠陥はありますか?
A:いくつかのマイナーな特典:
-トランザクションを開いたままにしてHTTPリクエストが完了するのを待つのは悪いことです。とにかく、データベースとHTTPの間でトランザクションの一貫性を実現することはできないため、HTTPが遅いときに、トランザクションが数分間続くリスクを冒さないでください。一般的なパターンは、{tran / receive/会話タイマーの開始/commit}を開始してから、DBxactを使用せずにHTTP呼び出しを発行することです。HTTP呼び出しが成功した場合は、{xactの開始/応答の送信/会話の終了/コミット}を行います。HTTPが失敗した場合(またはクライアントがクラッシュした場合)は、会話時間が再びアクティブになるようにします。タイマーメッセージ(本文なし)が表示されます。テーブルからハンドルに関連付けられているアイテムIDを取得する必要があります。

Q:注文完了状態の追跡が正しくないようです。より良い方法はありますか?たぶんQUEUERETENTIONを使用していますか?
A:あなたの状態追跡に対する私の1つの批判は、現在処理されているものが最後のものであるかどうかを判断するために注文アイテムをスキャンすることに依存していることです(5.3.4)。たとえば、これがアイテム状態で処理される「最後の」アイテムであるという情報を追加して、処理時に完了を報告する必要があることがわかるようにすることができます。RETENTIONは、デバッグの場合、または「論理ロールバック」を実行する必要のあるロジックがある場合、および会話エラーに対するアクションを補正する場合にのみ役立ちます。

Q:私の直感では、アクティブ化された外部exeが0以外の終了コードで終了することは決してないので、try {..} catch(Exception e){..} finally {Environment.Exit(0 )}メインで。この仮定は正しいですか?
A:最も重要なことは、アクティブ化されたプロセスがキューでRECEIVEステートメントを発行することです。そうしないと、キューモニターは通知された状態に永久に入る可能性があります。正しく覚えていれば、終了コードは関係ありません。他のバックグラウンドプロセスと同様に、例外をキャッチしてログに記録することが重要です。そうしないと、失敗し始めたときに問題があることすらわかりません。統制のとれたtry/catchブロックに加えて、UIアプリとUIアプリと非UIアプリの両方のフックApplication.ThreadExceptionアップAppDomain.UnhandledException

Q:DBコードでエラー処理をどのように整理しますか?エラーログテーブルで十分ですか?
A:これについては後でフォローアップします。エラーログテーブルで十分です。

Q:外部exe C#コードでエラー処理をどのように整理しますか?同じエラーログテーブル?
A:自分のアプリでこのような問題を処理する必要があったため、bugcollect.comを作成しました。問題はロギングだけではありません。集約と分析(少なくとも重複レポートの検出)が必要であり、「フィールドでの」展開構成の事故によるエラーの洪水を抑制します。真実は、今日、より多くのオプションがあります、例えば。exceptron.com。そしてもちろん、FogBugsにはロギング機能もあると思います。

Q:SQL Server Service Brokerの製品サンプルを見ましたが、Service Broker Interfaceは、一見単純なケースではやり過ぎのようです。より単純なServiceBrokerオブジェクトモデルの代替手段はありますか?
最後に、簡単な質問です。はい、それはやり過ぎです。単純なモデルはありません。

Q:少なくとも毒メッセージを排出できるService Broker用のクロスバージョンの「ポータブル」管理ツールはありますか?
A:ポイズンメッセージの問題は、ポイズンメッセージの定義がコードによって変わることです。ポイズンメッセージは、それを検出するために設定されている現在のガードを破るメッセージです

Q:上記のいずれかの適切なコードサンプルはありますか?
A:いいえ

もう1つのポイント:DB1からDB2への参照を避けるようにしてください(たとえば、4.3.4はDB1でアクティブ化され、DB2からitemsテーブルを読み取ります)。これにより、DB間の依存関係が作成され、a)1つのDBがオフライン(メンテナンスなど)または過負荷になるか、b)HA/DRのデータベースミラーリングを追加して1つのDBがフェイルオーバーしたときに壊れます。DB1とDB2が異なるマシン上にある(リンクサーバーがない)場合でも、コードが機能するようにしてください。必要に応じて、メッセージペイロードに情報を追加します。また、DB2を別のマシンに配置し、複数のDB2マシンを存在させて、HTTP/PDFの書き込み作業をスケールアウトできるように設計する場合。

そして最後に:この設計は非常に遅くなります。非常に多くのダイアログ/メッセージが含まれ、max_queue_readers 1がすべて含まれているため、1秒あたり数十のメッセージが遅くなっています。これは受け入れられる場合と受け入れられない場合があります。

于 2012-11-29T00:17:38.020 に答える