JMS (Java Messaging System) に似た独自の SOA スタイルのメッセージング システムを作成する方法を考えています。
MOM (メッセージング指向ミドルウェア) はメッセージを単一のデータベースに格納する必要がありますが、スケーラビリティとフェイルオーバーのために複数のサービスによって処理される場合があります。
基本的な Messages テーブルを次のように定義しました。
- MessageId int
- CreateTimeStamp 日時
- DeliveredTimeStamp 日時
- ペイロード varchar(最大)
- 有効期限
- RetryCount int
- 相関 ID int
- State int (1 - 待機中、2 - 処理中、3 - 送信済み、4 - 再試行、5 - 失敗)
- *ProcessIdLock int - メッセージを処理しているメッセージング サービスのプロセス ID です。
問題は、べき等性の問題は別として、1 つのサービスが一度に各メッセージを処理することを保証するにはどうすればよいかということです。
次のようなスキームを考えていました。
レコード ロックの実行: UPDATE メッセージ SET ProcessIdLock = MessageProcessorId, SET State = 2 -- Processing WHERE MessageId IN ( SELECT TOP 10 MessageId FROM Messages WHERE Expiration < GETTIME() + CreateTimeStamp AND State = 1 -- Waiting OR State = 3 -- Retry )
上記の手順では、1 つのサービスで一度に最大 10 個のメッセージを処理できます。
ロックされたレコードを取得します: SELECT Payload FROM Messages WHERE State = 2 -- Processing AND ProcessIdLock = MessageProcessorId
処理された各メッセージのステータスを更新します。UPDATE Messages
SET State = (Pass、Fail、または Retry)、SET DeliveredTimeStamp = GETDATE() -- Pass only WHERE MessageId = ProcessedMessageId
注: 私が抱えているもう 1 つの問題は、いくつかのメッセージが id でグループ化された複数のクライアントにブロードキャストされることです (つまり、合計 100 のクライアントが存在する可能性がありますが、各クライアント グループは 10 以下で構成されます)。
たとえば、グループに 5 つのクライアントがあり、現在 2 つのクライアントが切断されている場合はどうなりますか? それらのクライアントが戻ってきたら、そのメッセージを送信したいと思います。
一方のクライアントは再接続する可能性があり (メッセージを取得する必要があります)、もう一方のクライアントは再接続しない可能性があります (そのため、メッセージの有効期限が切れた後、メッセージは破棄されます)。
これを読んでくれてありがとう。私には典型的な企業の問題のように思えます。MSMQ は最適なソリューションでしょうか? 私は MSMQ を初めて使用します。MSMQ メッセージはストレージに保持されますか、それともメモリに保持されますか?