RabbitMQでは、キュー内で処理できないメッセージ(デッドレターと呼ばれる)は別のエクスチェンジに再度ルーティングされます。このエクスチェンジはデッドレターエクスチェンジと呼ばれ、デッドレターを処理するキューであるデッドレターキューに送信されます。
デッドレターキューの説明
上のイラストは、デッドレターの生成からそれらの処理までの全体のプロセスを表しています。
デッドレターの生成
以下はデッドレターが生成される条件です:
- メッセージが消費者によって手動で拒否され(basic.reject / basic.nack)、再キューがfalseに設定されている場合。
- メッセージの生存時間(TTL)が切れた場合。
- キューが最大長に達した場合。
デッドレターキューの処理手順
- デッドレターエクスチェンジを定義します(名前に惑わされないでください、通常のエクスチェンジです。デッドレター処理の文脈ではそのように呼ばれます)。
- デッドレターエクスチェンジにバインドするキューを定義します(このキューはデッドレターキューと呼ばれ、通常のキューでもあります)。
- デッドレターキューを消費するデッドレターコンシューマーを定義します(名前に惑わされないでください、これも通常のコンシューマーです)。
- デッドレターエクスチェンジを指定されたキューにバインドします(デッドレターを処理する必要のあるキューにバインドします)。
ヒント:原則については上記のイラストを参照してください。すべてのプログラミング言語はデッドレターキューを同様の方法で処理します。
Golangでのデッドレターキューの処理
1. デッドレターエクスチェンジを定義する
通常のエクスチェンジと同様に定義します。
// エクスチェンジを宣言
err = ch.ExchangeDeclare(
"tizi365.dead", // エクスチェンジ名
"topic", // エクスチェンジの種類
true, // 永続化
false,
false,
false,
nil,
)
2. デッドレターキューを定義する
通常のキューと同様に定義します。
// キューを宣言
q, err := ch.QueueDeclare(
"", // キュー名(空白の場合はランダムな名前が生成されます)
false, // キューの永続化
false,
true,
false,
nil,
)
// キューをデッドレターエクスチェンジにバインド
err = ch.QueueBind(
q.Name, // キュー名
"#", // ルーティングキー、# はすべてのルーティングキーに一致することを意味し、すべてのデッドレターメッセージを受信することを意味します
"tizi365.dead", // デッドレターエクスチェンジ名
false,
nil)
ヒント:デッドレターキューを通常のキューとして扱ってください。
3. デッドレターコンシューマーを定義する
// コンシューマーを作成
msgs, err := ch.Consume(
q.Name, // 以前に宣言したデッドレターキューの名前
"", // コンシューマー名(指定しない場合、ランダムな名前が生成されます)
true, // メッセージ処理の自動確認
false,
false,
false,
nil,
)
// デッドレターキューからのメッセージをループで消費
for d := range msgs {
log.Printf("デッドレターメッセージを受信=%s", d.Body)
}
4. デッドレターエクスチェンジを特定のキューにバインドする
// キューのプロパティ
props := make(map[string]interface{})
// デッドレターエクスチェンジをバインド
props["x-dead-letter-exchange"] = "tizi365.dead"
// 任意:デッドレターがデッドレターエクスチェンジに配信される際のルーティングキーを設定します。設定しない場合、元のメッセージのルーティングキーが使用されます。
// props["x-dead-letter-routing-key"] = "www.tizi365.com"
q, err := ch.QueueDeclare(
"tizi365.demo.hello", // キュー名
true, // 永続化
false, // 他は省略
false,
false,
props, // キュープロパティを設定
)
これにより、tizi365.demo.helloキュー内のメッセージがデッドレターとなった場合、それらはtizi365.deadデッドレターエクスチェンジに転送されます。