Nieprzetworzona wiadomość na kolejce blokuje przetworzenie kolejnych

0

Jak skonfigurować automatyczny mechanizm nack w spring boot tak, aby niedostarczona wiadomość (która jest znackowana z powodu np. lecącego wyjątku) nie powodowała zablokowania pozostałych wiadomości w kolejce? na teraz wygląda to jakby problematyczna wiadomość wracała na początek kolejki, blokując kolejne wpadające na kolejkę i powodując korek. Oto moja konfiguracja:

spring:
  rabbitmq:
    listener:
      simple:
        retry:
          enabled: true
          initial-interval: 2000
          max-attempts: 50
          max-interval: 10000
          multiplier: 1.5

listener:

@RabbitListener(queues = "someQueue", concurrency = "1-10")
public void SomeQueue(String message) {
    log.info("Received message to queue SomeQueue");
    someService.processMessage(message);
}

jeśli w someService.processMessage() poleci wyjątek, wiadomość znowu trafi z powrotem do kolejki.

scenariusz jaki chcę ograć to np someService łączy się z różnymi usługami zewnętrznymi, w zależności od wiadomości. jeśli jedna usługa zewnętrzna zawiedzie (tymczasowy downtime) to nie chciałbym, aby pozostałe wiadomości w kolejce, które nie polegają na tej konkretnej usłudze nie mogły być obsłużone. rozdział na kolejki dedykowane pod wywoływane pod spodem usługi nie wchodzi w grę.

na teraz mam wiadomość, w której poleciał wyjątek wraca na początek i blokuje następne:
Screenshot 2023-12-28 at 15.00.41.png

aplikacja chodzi na kilkanaście instancji spring boota.

dzięki!

1

Pytanie podstawowe, co ma się stać z tą wiadomością, której nie udaje się przetworzyć?

0
yarel napisał(a):

Pytanie podstawowe, co ma się stać z tą wiadomością, której nie udaje się przetworzyć?

ma zostać obsłużona ponownie w interwałach czasowych. w międzyczasie pozostałe wiadomości w kolejce również powinny być na bieżąco obsługiwane, a one wszystkie się kolejkują i czekają aż ta jedna problematyczna w końcu przejdzie.

0

W tej sytuacji najprostsze wydaje się przejście na ręczne NACK/ACK i obsługa zgodnie z pożądaną logiką. https://www.baeldung.com/spring-amqp-error-handling

0
yarel napisał(a):

W tej sytuacji najprostsze wydaje się przejście na ręczne NACK/ACK i obsługa zgodnie z pożądaną logiką. https://www.baeldung.com/spring-amqp-error-handling

ok dzięki.
a dlaczego spring blokuje takie wiadomości? nie da się skonfigurować springa tak, aby sam tym zarządzał?

0

kombinuję i widzę, że ustawienie concurrency = "1-10" na concurrency = "10" już pomaga, bo nie blokuje całej kolejki, jeśli jedna wiadomość utknie w wyjątkach.

1
hopsey napisał(a):
yarel napisał(a):

W tej sytuacji najprostsze wydaje się przejście na ręczne NACK/ACK i obsługa zgodnie z pożądaną logiką. https://www.baeldung.com/spring-amqp-error-handling

ok dzięki.
a dlaczego spring blokuje takie wiadomości? nie da się skonfigurować springa tak, aby sam tym zarządzał?

Ten fenomen nosi nazwę "head-of-line-blocking" i nie wiem czy da się to ogarnąć konfiguracją w springu, tak żeby było "tak jak chcesz".

Ręczne zarządzanie pozwoli taką logikę zaimplementować.
np.

  • Listener dostaje wiadomość -> serwis odpowiada -> ACK
  • Listener dostaje wiadomość -> leci wyjątek -> counter retry < MAX_ATTEMPTS -> zwiększ licznik w nagłówku wiadomości , wyślij do kolejki (trafi na koniec kolejki) -> ack oryginalnej wiadomości
  • Listener dostaje wiadomość -> leci wyjątek -> counter retry >=MAX_ATTEMPTS -> zrób coś z wiadomością po przekroczeniu max. liczby ponowień (no właśnie co? ) -> ack oryginalnej wiadomości

Może zamiast RETRY, to taką wiadomość wywalać do DeadLetterQueue i co jakiś czas z DLQ przerzucać do tej kolejki właściwej?

kombinuję i widzę, że ustawienie concurrency = "1-10" na concurrency = "10" już pomaga, bo nie blokuje całej kolejki, jeśli jedna wiadomość utknie w wyjątkach.

Wg mnie odsuwasz problem na jakiś czas ;-) Mówisz, że zamiast odpalać domyślnie 1 consumera i skalować (w miarę potrzeb) do 10, odpalasz od razu 10. Zauważ, że jeśli każdy z tych 10 consumerów dostanie problematyczną wiadomość, to wracasz do punktu wyjścia.

0
yarel napisał(a):
hopsey napisał(a):
yarel napisał(a):

W tej sytuacji najprostsze wydaje się przejście na ręczne NACK/ACK i obsługa zgodnie z pożądaną logiką. https://www.baeldung.com/spring-amqp-error-handling

ok dzięki.
a dlaczego spring blokuje takie wiadomości? nie da się skonfigurować springa tak, aby sam tym zarządzał?

Ten fenomen nosi nazwę "head-of-line-blocking" i nie wiem czy da się to ogarnąć konfiguracją w springu, tak żeby było "tak jak chcesz".

Ręczne zarządzanie pozwoli taką logikę zaimplementować.
np.

  • Listener dostaje wiadomość -> serwis odpowiada -> ACK
  • Listener dostaje wiadomość -> leci wyjątek -> counter retry < MAX_ATTEMPTS -> zwiększ licznik w nagłówku wiadomości , wyślij do kolejki (trafi na koniec kolejki) -> ack oryginalnej wiadomości
  • Listener dostaje wiadomość -> leci wyjątek -> counter retry >=MAX_ATTEMPTS -> zrób coś z wiadomością po przekroczeniu max. liczby ponowień (no właśnie co? ) -> ack oryginalnej wiadomości

Może zamiast RETRY, to taką wiadomość wywalać do DeadLetterQueue i co jakiś czas z DLQ przerzucać do tej kolejki właściwej?

kombinuję i widzę, że ustawienie concurrency = "1-10" na concurrency = "10" już pomaga, bo nie blokuje całej kolejki, jeśli jedna wiadomość utknie w wyjątkach.

Wg mnie odsuwasz problem na jakiś czas ;-) Mówisz, że zamiast odpalać domyślnie 1 consumera i skalować (w miarę potrzeb) do 10, odpalasz od razu 10. Zauważ, że jeśli każdy z tych 10 consumerów dostanie problematyczną wiadomość, to wracasz do punktu wyjścia.

rozważmy jeszcze jeden przypadek. co w opisanym przez Ciebie scenariuszu, jeżeli cały kontener się wywróci w połowie wykonywania taska? jeżeli dobrze rozumiem, jeżeli damy ack przy zdjęciu wiadomości z kolejki, nie wróci ona w przypadku wstrzymania kontenera.
czy da się taki scenariusz jakoś ograć implementując tę logikę ręcznie?

0
hopsey napisał(a):

...

rozważmy jeszcze jeden przypadek. co w opisanym przez Ciebie scenariuszu, jeżeli cały kontener się wywróci w połowie wykonywania taska? jeżeli dobrze rozumiem, jeżeli damy ack przy zdjęciu wiadomości z kolejki, nie wróci ona w przypadku wstrzymania kontenera.
czy da się taki scenariusz jakoś ograć implementując tę logikę ręcznie?

Ack dajemy po przetworzeniu, a nie po zdjęciu z kolejki.

0

A czemu nie korzystasz z DLQ?

1 użytkowników online, w tym zalogowanych: 0, gości: 1