RabbitMQ i zabezpieczanie się przed duplikacją wiadomości oraz złą kolejnością.

0

Hej. Załóżmy, że RabbitaMQ mamy skonfigurowanego ze strategią "przynajmniej raz" i dodatkowo mamy kilka równoległych konsumerów w celu lepszej wydajności.

Jak zabezpieczacię się przez przyjmowaniem eventów w złej koleności -> np najpierw item.removed a potem item.created ?
Jak zabezpieczacię się przed otrzymaniem tego samego eventu kilka razy?

0

ad 1. nie do końca rozumiem o co ci chodzi - domyślnie kolejka jest FIFO
ad 2. tym zajmuje się rabbit, wysyła wiadomość do jednego konsumentów i oznacza wiadomość jako unacked(inny konsument nie otrzyma tej wiadomości) i zostaje tak do otrzymania odpowiedzi lub utraty połączenia z kanałem który otrzymał wiadomość -> jako konsument za pomocą kanału odsyłasz czy dana wiadomość została poprawnie przetworzona - ack(wiadomość zostaje usunięta z kolejki) lub nie - nack (w metodzie powinien być jakiś boolean który definuje czy dana wiadomość ma pozostać w kolejce aby można było ją ponownie skonumować czy zniknąć)

2
Bambo napisał(a):

Jak zabezpieczacię się przed otrzymaniem tego samego eventu kilka razy?

Trzeba tak napisać operacje wykonywane przez konsumentów żeby były idempotentne :P

Bo nawet jak Rabbit dba o to, żeby dwóch konsumentów nie otrzymało jednocześnie tej samej wiadomości to zawsze jest szansa,że konsument dostanie wiadomość, wykona operację, ale wywali się na potwierdzaniu wykonania wiadomości w Rabbicie (nie zrobi ACK) i wtedy ta sama wiadomość zostanie przetworzona i tak jeszcze raz.

0

@ZabawnyNick @some_ONE:

Mam idempotentne wiadomości, ale jeśli nasłuchuję na event który wysyła maila? No to już jednak trochę trudniej no nie? Ewentualnie dać do payloada eventu jakiś UUID i trzymać sobie w bazie UUIDy które przetworzyłem.

A z tą kolejnością chodziło mi o to, że jeśli jakiś mikroserwis nasłuchuje na dwa eventy: item.updated i item.removed i z jakiegoś powodu dostanie je nie w tej kolejności w jakiej zaszły w systemie czyli:

  1. item.removed
  2. item.created
    Może to być spowodowane tym, że mikroserwis ma kilku kilku konsumerów dla lepszej wydajności.

to też jest problem.

0

Z tego co opisujesz o kolejności to nasuwa mi się taki obraz:
Twój system stworzył 4 wiadomości i wysłał je do rabbita, lecz nie ma kto ich odebrać więc czekają sobie tak w kolejce.
wiadomości wyglądają następująco:

item1.update
itemXX.something
itemXY.something
item1.delete

Następnie uruchamiasz 4 konsumentów i każdy dostaję po 1 wiadomości w tym samym czasie( każdy dostał inną o to zadbał rabbit ), ale jak widać dla item1 następuje wyścig.

Mój pomysł rozwiązania problemu: (wymaga dodatkowych założeń)
item - zakładam że jest to coś na czym trzeba wykonać daną operację -> np dane które pobieram z bazy
item - dodaje do coś'a pole które definiuje mi jego wersję, oraz dodaję ją w wiadomości w rabicie -> każda operacja na coś'u będzie podnosić jego wersje o 1

i teraz jako konsument sprawdzam czy wersja z wiadomości coś'ia jest równa z tego co pobieram z bazy, jeżeli tak to ją wykonuje, jeżeli nie to odczekuje jakiś czas (chodzi o to aby wiadomość nie robiła kółek z kolejki do konsumenta i z powrotem w czasie przetwarzania wiadomości z dobrą wersją przez innego konsumenta) i wysyłam ją ponownie, lub odsyłam ją jako NACK - zależnie czy wolę aby trafiła na koniec kolejki czy początek, jednak nie będzie to działać jeżeli nie jesteś w stanie zapewnić unikalności wersji dla każdej z zmiany dla item i np do kolejki będą mogły trafić wiadomości item1.update oraz item1.delete z tą samą jego wersją.

Nie wiem czy wytłumaczyłem to w zrozumiały sposób, nie przychodzi mi też obecnie żaden inny pomysł do głowy

co do wysyłania tych maili to nie powinno być problemu tak długo jak po każdej wiadomości potwierdzasz jej przetworzenie przez ACK, oczywiście przypadek który opisał @some_ONE jest jak najbardziej możliwy, nie jestem stanie stwierdzić jak często może wystąpić bo dopiero u siebie wdrażamy rabbitamq, osobiście wykorzystuje springa i tam można ustawić ilość prób dostarczenia wiadomości oraz odstęp między nimi, ale takie rzeczy da się napisać i z palca w każdym języku.

Pamiętaj że rabbitamq da się ustawić oczywiście aby pracował w trybie mirror i mieć więcej instancji.

Zapomniałem dodać, w rabbicie można ustawić prefetch wiadomości czyli ilość wiadomości którą rezerwuje sobie dany konsument do przetworzenia, wtedy nikt też nie powinien ich podkraść, może pójście w tą stronę będzie w stanie rozwiązać twój problem z ich kolejnością.

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