MSMQ移行判断の知識マップ(知識グラフ)
MSMQはOS機能としては2026年7月時点でも非推奨になっていませんが、これを扱う標準ライブラリSystem.Messagingは.NET Frameworkにしか存在せず、.NET(Core以降)への公式な道はありません。CoreWCFによる移植やネイティブAPIのP/Invokeは延命手段止まりで、新規採用も推奨できません。移行判断の軸は「アプリを.NETへ上げるか」で、上げるならMSMQ+DTCが担っていた整合性を、業務データと同一のローカルトランザクションで確定できるDBのテーブルキューに置き換えるのが第一候補です。複数システム間の疎結合な連携が必要な場合に限り、RabbitMQやAzure Service Busを検討します。テーブルキューの実装ではREADPASTヒントとREAD_COMMITTED_SNAPSHOTデータベースオプションの組み合わせに注意が要ります。
MSMQ(Microsoft Message Queuing)
Windowsに同梱されてきたメッセージキュー基盤。store-and-forward・トランザクション・OS同梱を特徴とし、2026年7月時点で公式の非推奨機能一覧には載っていない。
System.Messaging
MSMQを扱う.NETの標準クラスライブラリ。対象バージョンは.NET Framework 1.1〜4.8.1のみで、.NET(Core以降)向けの版は存在しない。
MessageQueueクラス
DTC(分散トランザクションコーディネーター)
複数のリソース(MSMQのキューとデータベースなど)にまたがるトランザクションを調停するWindowsのサービス。クラウド系のキューサービスは参加できない。
分散トランザクション
トランザクションキュー
トランザクションメッセージだけを扱うMSMQのキュー。作成時に決まり、後から変更できない。
expressメッセージ
MSMQの既定の送信モード。配送中も配送後もメモリ上に置かれ高速だが、MSMQサービスやマシンの再起動で失われる。
recoverable(回復可能)メッセージ
送信側と中継する各コンピューターでディスクに書かれ、宛先キューでもディスク上に保持されるMSMQの送信モード。再起動をまたいで残る。
ジャーナルキュー
送信した・取り出したメッセージの控えを保持する、MSMQが自動生成するシステムキュー。放置すると容量を食うため塩漬け運用では監視対象になる。
配信不能(デッドレター)キュー
届けられなかったメッセージを保持する、MSMQが自動生成するシステムキュー。
配信不能キュー
プライベートキュー
ディレクトリサービス(Active Directory)には発行せず、そのコンピューター上にだけ登録されるMSMQのキュー。中小規模の業務システムで使われているのはほとんどがこちら。対するパブリックキューはディレクトリサービスに登録される。
パブリックキュー
再起動時のメッセージ喪失
MSMQサービスやマシンの再起動によって、メモリ上にしか無いメッセージが失われること。
.NET Framework
Windowsのコンポーネントとして扱われ、インストールされているOSのライフサイクルに沿ってサポートされるランタイム。System.Messagingの対象範囲。
.NET(Core以降)
.NET Frameworkの後継となる、クロスプラットフォーム対応の.NETランタイム(.NET 5以降)。
モダンな.NET
MSMQのWin32ネイティブAPI
MQSendMessage・MQReceiveMessageなど、MSMQをC/C++向けに操作する文書化されたWin32 API。.NETからP/Invokeで呼ぶことも可能だが、フォーマッターやトランザクション連携は自前で書く延命手段。
CoreWCF
WCFのサーバー側を.NETに移植するコミュニティ主導プロジェクト。マイクロソフトが公式なサポートポリシーを提供する一方、MSMQ対応パッケージ(CoreWCF.MSMQ)はSystem.Messagingのコミュニティ移植に依存する。
DBのテーブルキュー
データベースのテーブルをキューとして使う設計。メッセージの取り出しと業務データの更新を同一のローカルトランザクションで確定でき、MSMQ+DTCの整合性をより単純な仕組みで置き換えられる。
テーブルキュー
RabbitMQ
オンプレミスで運用できるメッセージブローカー。複数システム・複数言語間の疎結合な連携やファンアウト配信が得意な一方、自前運用の冗長化・更新の負荷を伴う。
Azure Service Bus
クラウド上で運用できるメッセージブローカー。複数システム間の疎結合な連携に向くが、DTCには参加できない。
複数システム・複数言語間の疎結合な連携
配信のファンアウトやルーティングが必要な、複数システム・複数言語にまたがる非同期連携の要件。
BinaryFormatter
セキュリティ上の理由から段階的に廃止された.NETのバイナリ直列化機構。.NET 9以降はランタイムから実装が削除され既定では使用できない。
Outboxパターン
送信側で業務データの更新とメッセージ行のINSERTを同一トランザクションに入れ、業務データは更新されたのにメッセージが出ていないという不整合を防ぐ設計。
READPASTテーブルヒント
他のトランザクションがロックしている行を読まずに飛ばすSQL Serverのテーブルヒント。複数ワーカーによるテーブルキューの並列な取り出しに使う。行ロックは飛ばせるがページロックは飛ばせない。
READ_COMMITTED_SNAPSHOTデータベースオプション
読み取りのブロッキング対策として行バージョニングを使うデータベースオプション。ONのときセッションの分離レベルがREAD COMMITTEDだと、READCOMMITTEDLOCKヒントの併記なしにREADPASTを指定できない。Azure SQL Databaseでは既定でON。
新規プロジェクトでの新規採用
これから作るシステムで、ある技術(メッセージキューやUI自動化ツールなど)を新規に選定・採用すること。
MSMQはMS DTC(分散トランザクションコーディネーター)と組み合わせて、キューからの取り出しとデータベース更新を1つの分散トランザクションで確定できる
MSMQはトランザクションメッセージだけを扱うトランザクションキューを持てる
MSMQの既定の送信モードはexpressメッセージ
送信側が明示的に指定すると、MSMQはメッセージをディスクに永続化するrecoverableモードで扱える
MSMQは送受信の控えを保持するジャーナルキューを自動生成する
MSMQは届けられなかったメッセージを保持する配信不能キューを自動生成する
中小規模の業務システムで使われているMSMQのキューは、ほとんどがディレクトリサービスに発行しないプライベートキュー
expressメッセージはメモリ上に留まり得るため、MSMQサービスやマシンの再起動でメッセージが失われる
recoverableメッセージはディスクに書かれるため、再起動をまたいで残る
System.Messaging.MessageQueueクラスのリファレンスが対象とするのは.NET Framework 1.1から4.8.1まで
.NET(Core以降)向けのSystem.Messaging版は存在せず、公式なマネージドAPIの道が閉じている
.NETからMSMQのWin32ネイティブAPIをP/Invokeで呼ぶことは技術的には可能だが、フォーマッターやトランザクション連携を自前で書いて保守する延命手段になる
MQSendMessageなどのネイティブAPIはMSMQ自体が有効化・インストールされていることを前提とする
CoreWCFのMSMQトランスポート(CoreWCF.MSMQ)の実装は.NET Framework版System.Messagingライブラリのコミュニティ移植に依存している
中小規模の業務システムでMSMQが担っていた非同期処理の移行先として、本記事はDBのテーブルキューを第一候補として位置付ける
MSMQのトランザクションキューとDB更新をアトミックに扱うには、DTCによる分散トランザクションが必要だった
MSMQ+DTCで実現していた整合性は、業務データと同一のローカルトランザクションで確定できるテーブルキューに置き換えるのが本記事の推奨
クラウド系キューはDTCに参加できないため、この要件がある限りRabbitMQへの移行は遠回りになる
Azure Service BusもDTCに参加できないため、DTC要件がある限り移行の遠回りになる
配信のファンアウトやルーティングが必要な、複数システム・複数言語間の疎結合な連携にはRabbitMQ(オンプレ)が候補になる
クラウドに置ける場合、複数システム間の疎結合な連携にはAzure Service Busが候補になる
配信のファンアウトやルーティングが必要な複数システム・複数言語間の連携には、テーブルキューでは要件が足りないことがある
BinaryFormatterは.NET 9以降ランタイムから実装が削除され既定では使用できないが、非サポートのSystem.Runtime.Serialization.Formattersパッケージに明示的に依存させれば、引き続き利用できる場合がある
移行先がモダンな.NETの場合、BinaryFormatterは実装が削除されているため、テーブルキューへ移す新システムにこの直列化形式は持ち込めず、JSONなどへの置き換えが必要になる
送信側でメッセージの出し漏れを防ぎたい場合は、業務データの更新とメッセージ行のINSERTを同一トランザクションに入れるOutboxパターンを使う
SQL Serverでは、テーブルキューの取り出しはREADPASTヒントを使うことで、他のワーカーがロックしている行を待たずに飛ばし、複数プロセスで同時に回せる
READ_COMMITTED_SNAPSHOTがONでセッションの分離レベルがREAD COMMITTEDのとき、READCOMMITTEDLOCKヒントの併記なしにREADPASTは指定できず、文そのものがエラーになる
公式な将来の道(モダンな.NETからの利用手段)がないため、新規プロジェクトでのMSMQ新規採用は推奨できない