W RabbitMQ, gdy wiadomość staje się tzw. dead letter (wiadomość, którą konsumenci nie mogą przetworzyć) w kolejce, jest ona przekierowywana do innej wymiany, którą nazywamy wymianą dead letter. Wymiana dead letter przesyła wtedy martwą wiadomość do kolejki, którą jest kolejka dead letter.

Ilustracja kolejki dead letter

Dead Letter Queue

Powyższa ilustracja opisuje cały proces od generacji dead letter do ich obsługi.

Generacja Dead Letter

Poniżej znajdują się warunki generacji dead letter:

  • Wiadomość jest ręcznie odrzucana przez konsumenta (basic.reject / basic.nack), a requeue = false.
  • Czas życia (TTL) wiadomości wygasa.
  • Kolejka osiąga maksymalną długość.

Kroki Obsługi Kolejki Dead Letter

  1. Zdefiniuj wymianę dead letter (nie daj się zwieść nazwie, to tylko zwykła wymiana, tak nazywa się ją tylko w kontekście obsługi dead letter).
  2. Zdefiniuj kolejkę do powiązania z wymianą dead letter (ta kolejka nazywana jest kolejką dead letter, to również zwykła kolejka).
  3. Zdefiniuj konsumenta dead letter do konsumowania kolejki dead letter (nie daj się zwieść nazwie, to również zwykły konsument).
  4. Powiąż wymianę dead letter z określoną kolejką (powinna być powiązana kolejka, która musi obsługiwać dead letter).

Wskazówka: Odnośnie zasady, patrz na powyższą ilustrację. Wszystkie języki programowania obsługują kolejkę dead letter w podobny sposób.

Obsługa Kolejki Dead Letter w języku Golang

1. Zdefiniuj Wymianę Dead Letter

Zdefiniuj ją jak zwykłą wymianę.

// Zadeklaruj wymianę
err = ch.ExchangeDeclare(
    "tizi365.dead",   // Nazwa wymiany
    "topic", // Typ wymiany
    true,     // Trwała
    false,
    false,
    false,
    nil,
)

2. Zdefiniuj Kolejkę Dead Letter

Zdefiniuj ją jak zwykłą kolejkę.

    // Zadeklaruj kolejkę
    q, err := ch.QueueDeclare(
        "",    // Nazwa kolejki, pozostaw pustą, aby wygenerować losową
        false, // Trwała kolejka
        false,
        true,
        false,
        nil,
    )

    // Powiąż kolejkę z wymianą dead letter
    err = ch.QueueBind(
        q.Name, // Nazwa kolejki
        "#",     // Klucz routingu, # oznacza dopasuj wszystkie klucze routingu, co oznacza odbierz wszystkie wiadomości dead letter
        "tizi365.dead", // Nazwa wymiany dead letter
        false,
        nil)

Wskazówka: Traktuj kolejkę dead letter jak zwykłą kolejkę.

3. Zdefiniuj Konsumenta Dead Letter

// Utwórz konsumenta
msgs, err := ch.Consume(
    q.Name, // Odwołaj się do wcześniejszej nazwy kolejki dead letter
    "",     // Nazwa konsumenta, jeśli nie podano, zostanie wygenerowana losowa
    true,   // Automatyczne potwierdzenie przetwarzania wiadomości
    false, 
    false, 
    false, 
    nil,
)

// Pętla do konsumowania wiadomości z kolejki dead letter
for d := range msgs {
    log.Printf("Otrzymano wiadomość dead letter=%s", d.Body)
}

4. Powiąż wymianę dead letter z określoną kolejką

	// Właściwości kolejki
	props := make(map[string]interface{})
	// Powiąż wymianę dead letter
	props["x-dead-letter-exchange"] = "tizi365.dead"
	// Opcjonalnie: Ustaw klucz routingu, gdy dead letter jest dostarczany do wymiany dead letter. Jeśli nie jest ustawiony, zostanie użyty oryginalny klucz routingu wiadomości.
	// props["x-dead-letter-routing-key"] = "www.tizi365.com"

	q, err := ch.QueueDeclare(
		"tizi365.demo.hello", // Nazwa kolejki
		true,   // Trwała
		false, 
		false, 
		false,   
		props,     // Ustaw właściwości kolejki
	)

W ten sposób, jeśli wiadomości w kolejce tizi365.demo.hello staną się dead letter, zostaną przekierowane do wymiany dead letter tizi365.dead.