Mam system, w którym klient (nazwijmy go ClientA) może publikować żądania na określony temat MQTT. Pośrednikiem, jeśli ma to znaczenie, jest Amazon Web Services. Następnie mam innego klienta (nazwijmy go MainSubscriber), który zawsze subskrybuje ten sam temat, aby mógł odbierać żądania od ClientA i wykonywać pewne prace, które ostatecznie zamieniają się w operację bazy danych. Baza danych, jeśli ma to znaczenie, to DynamoDB.
Ponieważ subskrybent główny może nie zawsze być dostępny / online, istnieje potrzeba posiadania abonenta przełączania awaryjnego, który byłby kopią zapasową przełączania awaryjnego głównego subskrybenta. Chodzi o to, że jeśli główny subskrybent nie obsłuży żądania w odpowiednim czasie, wówczas subskrybent pracy awaryjnej uruchomi się i wykona równoważną operację praca / baza danych. Wyzwanie polega na tym, że „praca” i wynikająca z niej „operacja bazy danych” nie mogą być powielane przez abonentów głównych i przełączników awaryjnych.
Oto logiczny rysunek architektury systemu dla tego systemu.
-----> MainSubscriber ----
/ \
ClientA --> Broker ---> Database
\ /
---> FailoverSubscriber --
Oczywiście z takim systemem wiążą się pewne wyzwania:
- W jaki sposób główny subskrybent informuje subskrybenta trybu failover, że działa na żądanie?
- W jaki sposób subskrybent pracy awaryjnej wykrywa, że główny subskrybent nie odebrał żądania i musi zacząć nad nim pracować?
- W jaki sposób subskrybent pracy awaryjnej powstrzymuje głównego subskrybenta, jeśli nagle nagle wróci do trybu online i odbierze żądanie?
- Jak poradzić sobie z problemami synchroniczności między abonentami głównymi i przełączeniami awaryjnymi?
Wolałbym nie wymyślać na nowo koła, jeśli istnieje już istniejące rozwiązanie dla takiego programu. Moje pierwsze pytanie brzmi: czy coś już tam jest?
Jeśli nie, to zastanawiałem się nad użyciem DynamoDB z silnie spójnymi odczytami, które mogłyby pełnić rolę mediatora między abonentem głównym a abonentem przełączania awaryjnego. Moje drugie pytanie brzmi zatem, czy istnieją dobrze ugruntowane programy tego typu?
Odpowiedzi:
Zgodnie z dokumentacją AWS SQS (jak powiedziałeś, brokerem jest AWS), powinno to być natywne:
Problem polega na znalezieniu odpowiedniego limitu czasu widoczności zgodnie z maksymalnym czasem przetwarzania.
Nadal masz niewielką szansę, aby zarówno subskrybent przetworzył ten sam komunikat, w tym przypadku kod subskrybenta powinien spróbować utworzyć idempotentne wyjście dla bazy danych (przynajmniej ten sam klucz podstawowy) i powinieneś z gracją poradzić sobie z niepowodzeniem podczas próby wstawienia tego samego rekordu.
źródło
Być może warto przyjrzeć się koncepcji kolejki niedostarczonych komunikatów AWS SQS . Z dokumentów AWS:
Jeśli więc wskażesz subskrybentowi głównemu, aby nasłuchiwał z normalnej kolejki, a subskrybentowi wtórnemu, aby nasłuchiwał z kolejki niedostarczonych komunikatów, problem przełączenia awaryjnego powinien zostać rozwiązany.
Dzięki temu rozwiązano 1, 2 i 3 problemy. W tym przypadku główny i pomocniczy subskrybenci nie muszą ze sobą rozmawiać.
Opierając się również na odpowiedzi Tensibai, upewnij się, że kod subskrybenta jest zapisany, aby otrzymywać jedną wiadomość na raz, jeśli wielu subskrybentów nasłuchuje tej samej kolejki z powodu
visibility timeout
Minusem byłoby to, że wprowadziłoby opóźnienie w przetwarzaniu, wiadomości trafiają do kolejki niedostarczonych wiadomości dopiero po pewnym czasie.
Jeśli więc tego nie chcesz, możesz przejść do odpowiedzi Tensibai. A jeśli możesz to tolerować, zamiast posiadania dodatkowej tabeli Dynamo do sprawdzania statusu, możesz tego użyć.
źródło