RabbitMQでは、キュー内で処理できないメッセージ(デッドレターと呼ばれる)は別のエクスチェンジに再度ルーティングされます。このエクスチェンジはデッドレターエクスチェンジと呼ばれ、デッドレターを処理するキューであるデッドレターキューに送信されます。

デッドレターキューの説明

デッドレターキュー

上のイラストは、デッドレターの生成からそれらの処理までの全体のプロセスを表しています。

デッドレターの生成

以下はデッドレターが生成される条件です:

  • メッセージが消費者によって手動で拒否され(basic.reject / basic.nack)、再キューがfalseに設定されている場合。
  • メッセージの生存時間(TTL)が切れた場合。
  • キューが最大長に達した場合。

デッドレターキューの処理手順

  1. デッドレターエクスチェンジを定義します(名前に惑わされないでください、通常のエクスチェンジです。デッドレター処理の文脈ではそのように呼ばれます)。
  2. デッドレターエクスチェンジにバインドするキューを定義します(このキューはデッドレターキューと呼ばれ、通常のキューでもあります)。
  3. デッドレターキューを消費するデッドレターコンシューマーを定義します(名前に惑わされないでください、これも通常のコンシューマーです)。
  4. デッドレターエクスチェンジを指定されたキューにバインドします(デッドレターを処理する必要のあるキューにバインドします)。

ヒント:原則については上記のイラストを参照してください。すべてのプログラミング言語はデッドレターキューを同様の方法で処理します。

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デッドレターエクスチェンジに転送されます。