Jak zaprojektować skalowalny system powiadomień? [Zamknięte]

32

Muszę napisać menedżera systemu powiadomień.

Oto moje wymagania:

Muszę być w stanie wysłać powiadomienie na różnych platformach, które mogą być zupełnie inne (na przykład muszę mieć możliwość wysłania wiadomości SMS lub e-mail).

Czasami powiadomienie może być takie samo dla wszystkich odbiorców na danej platformie, ale czasami może to być powiadomienie na odbiorców (lub kilku) na platformę.

Każde powiadomienie może zawierać ładunek specyficzny dla platformy (na przykład wiadomość MMS może zawierać dźwięk lub obraz).

System musi być skalowalny , muszę być w stanie wysłać bardzo dużą liczbę powiadomień bez awarii aplikacji lub serwera.

Jest to proces dwuetapowy. Najpierw klient może wpisać wiadomość i wybrać platformę, na którą ma zostać wysłany, a powiadomienia należy utworzyć w celu przetworzenia w czasie rzeczywistym albo później.

Następnie system musi wysłać powiadomienie do dostawcy platformy.


Na razie jednak mam kilka, ale nie wiem, jak będzie skalowalny lub czy to dobry projekt.

Myślałem o następujących obiektach (w pseudo języku):

Notificationobiekt ogólny :

class Notification {
    String                 $message;
    Payload                $payload;
    Collection<Recipient>  $recipients;
}

Problem z następującymi obiektami polega na tym, że mam 1.000.000 odbiorców? Nawet jeśli Recipientobiekt jest bardzo mały, zajmie zbyt dużo pamięci.

Mógłbym również utworzyć jedno powiadomienie dla odbiorcy, ale niektórzy dostawcy platformy wymagają ode mnie wysyłania go partiami, co oznacza, że ​​muszę zdefiniować jedno powiadomienie z kilkoma odbiorcami.

Każde utworzone powiadomienie może być przechowywane w trwałym magazynie, takim jak DB lub Redis.

Czy dobrze byłoby agregować to później, aby upewnić się, że jest skalowalne?

Na drugim etapie muszę przetworzyć to powiadomienie.

Ale jak mogę odróżnić powiadomienie od odpowiedniego dostawcy platformy?

Czy powinienem użyć obiektu takiego jak MMSNotificationrozszerzenie abstract Notification? czy coś w tym stylu Notification.setType('MMS')?

Myślę, że aby umożliwić przetwarzanie wielu powiadomień w tym samym czasie, system kolejki przesyłania wiadomości, taki jak RabbitMQ, może być właściwym narzędziem. Czy to jest

Pozwoliłoby mi to ustawić w kolejce wiele powiadomień i umożliwić kilku pracownikom wyskakiwanie powiadomień i ich przetwarzanie. Ale co, jeśli będę musiał wysyłać odbiorców, jak pokazano powyżej?

Potem wyobrażam sobie, że NotificationProcessorobiekt, do którego mógłbym dodać NotificationHandlerkażdy, NotificationHandlerbyłby odpowiedzialny za połączenie dostawcy platformy i wykonanie powiadomienia.

Mogę również użyć, EventManageraby umożliwić zachowanie wtykowe.

Wszelkie informacje zwrotne lub pomysły?

Dziękuję za poświęcony czas.

Uwaga: Jestem przyzwyczajony do pracy w PHP i jest to prawdopodobnie wybrany przeze mnie język.


Edycja (zgodnie z odpowiedzią morphunreal)

  • Ile wiadomości na sekundę wysyłasz (Zdefiniuj poziomy bieżący / początkowy, określ maksymalny poziom, który system powinien obsługiwać przed przeprojektowaniem)
  • Jakie ograniczenia sprzętowe ma system (pamięć, procesor itp. Dostępne dla systemu)
  • Jak skaluje się sprzęt (tj. Dodając więcej serwerów, przetwarzanie w chmurze itp.)

  • W jakich językach / systemach będą generowane powiadomienia?

To sam, jestem odpowiedzialny za programowe tworzenie powiadomień, ale zbudowane z interfejsu użytkownika.

  • Czy generator zna odbiorców wiadomości (?), Czy są udostępniane w inny sposób (np. Reguły biznesowe dla niektórych typów alertów są kierowane do niektórych odbiorców)

Powinno być możliwe utworzenie powiadomienia dla określonych odbiorców, grupy odbiorców (na przykład za pomocą systemu tagów) lub dla całej platformy.

  • Czy istnieją reguły biznesowe dotyczące dodawania rachunków CC / BCC / Read

Tak. Zauważ, że jest to naprawdę specyficzne dla platformy i odczyt lub DW nie są dostępne na wszystkich platformach.

  • Czy generator zna typ wiadomości, którą wysyła (tj. SMS / e-mail), czy też jest oparty na odbiorcy?

Opiera się on na odbiorcy, jednak ponieważ odbiorca jest powiązany z platformą, a platformy mają inny sposób obsługi danych, interfejs użytkownika prawdopodobnie będzie specyficzny dla platformy, umożliwiając konfigurację obrazów, dźwięku lub czegoś takiego.

  • Czy generator wymaga potwierdzenia wysyłania / odbierania / odczytu wiadomości (asynchroniczne vs wysyłanie synchroniczne)

Cóż, system powinien być podatny na błędy, ale chcielibyśmy obsłużyć błąd w celu zdefiniowania zestawu reguł, na przykład jeśli serwer jest nieosiągalny, powiadomienie powinno być wymagane do dalszego przetwarzania, ale jeśli powiadomienie jest nieprawidłowe (lub zostało zdefiniowane przez dostawcę platformy) nie należy tego wymagać, ale powiadamiać.

  • Czy istnieją wymagania dotyczące przechowywania historii źródeł / odbiorców wiadomości (jak długo?)

Tak, prawdopodobnie chcemy stworzyć statystyki i raporty. * Zdefiniuj punkty końcowe powiadomień


  • Jakie usługi są używane do wysyłania wiadomości? Zależy, niektóre są klasyczną usługą REST, inne są jakimś egzotycznym protokołem, to naprawdę zależy od dostawcy.

  • Jakie informacje zwrotne / potwierdzenia są przekazywane (synchronizacja / asynchronizacja)

Zależy, niektóre są zsynchronizowane i odpowiadają z błędem, podczas gdy inne muszą zostać pociągnięte, aby sprawdzić błędy.

  • Czy to możliwe, aby dodać nowe punkty końcowe [nawet jeśli tak, to czy to nawet wymaga abstrakcji]

Tak, właściwie nasza aplikacja rośnie i prawdopodobnie chcemy dodać nowego dostawcę, ale jest to stosunek około 1 lub 2 rocznie.

Trent
źródło
22
Walter, komar, gbjbaanb, Robert Harvey, Thorsten Müller wydają się być leniwymi ludźmi; Nie widzę powodu, dla którego to pytanie zostało zamknięte z powodu jednego z następujących argumentów: „dwuznaczny, niejasny, niekompletny, zbyt szeroki lub retoryczny”. Pytanie projektowe nie może być prostym pytaniem, ponieważ wiąże się z bardzo wieloma rzeczami, myślałem jednak, że poziom tej witryny pozwala omawiać tak złożone decyzje z prawdziwym profesjonalistą.
Trent
Zadawaj pytania, ale nie zadawaj pytań! :) Tak, czasami ja też nie rozumiem mentalności modów.
Mrchief,
opinie i poglądy pokazują, jak ważne jest to pytanie ... gdyby tylko moderatorzy zrozumieliby !!!
NoobEditor
Korzystanie z RabbitMQ jest właściwym podejściem do tego problemu. Poproszono mnie o bardzo podobny problem w jednym z moich wywiadów z DUŻĄ firmą i walczyłem z najlepszym wzorcem wydawcy / subskrybenta odpornego na błędy. Na koniec powiedziano mi prawidłową odpowiedź. RabbitMQ. Wygląda na to, że rozwiązali problem, używając go. Mam nadzieję, że to pomaga !!!
AkD

Odpowiedzi:

16

Zacznij od oddzielenia wymagań funkcjonalnych i niefunkcjonalnych i dokładnego ich zdefiniowania. Bardzo łatwo jest przeprojektować system oparty na niejednoznacznych wymaganiach.

Na przykład Twoje niefunkcjonalne wymagania dotyczące skalowalności są dość niejednoznaczne. Może zmniejszyć obciążenie psychiczne, jeśli umieścisz rzeczywiste liczby w systemie. Na przykład,

  • Ile wiadomości na sekundę wysyłasz (Zdefiniuj poziomy bieżący / początkowy, określ maksymalny poziom, który system powinien obsługiwać przed przeprojektowaniem)
  • Jakie ograniczenia sprzętowe ma system (pamięć, procesor itp. Dostępne dla systemu)
  • Jak skaluje się sprzęt (tj. Dodając więcej serwerów, przetwarzanie w chmurze itp.)

Teraz, gdy masz to na uwadze, możesz skonfigurować kilka testów, aby upewnić się, że projekt / architektura systemu jest w stanie spełnić Twoje niefunkcjonalne wymagania.

Jeśli chodzi o biznesowe / funkcjonalne wymagania dotyczące wysyłania powiadomień / wiadomości, pomocne mogą być następujące wskazówki (jeśli podasz więcej informacji, mogę dodać do tej odpowiedzi):

Zdefiniuj źródła powiadomień

  • Jakie języki / systemy będą generować powiadomienia
  • Czy generator zna odbiorców wiadomości (?), Czy są udostępniane w inny sposób (np. Reguły biznesowe dla niektórych typów alertów są kierowane do niektórych odbiorców)
  • Czy istnieją reguły biznesowe dotyczące dodawania rachunków CC / BCC / Read
  • Czy generator zna typ wiadomości, którą wysyła (tj. SMS / e-mail), czy też jest oparty na odbiorcy?
  • Czy generator wymaga potwierdzenia wysyłania / odbierania / odczytu wiadomości (asynchroniczne vs wysyłanie synchroniczne)
  • Czy istnieją wymagania dotyczące przechowywania historii źródeł / odbiorców wiadomości (jak długo?)

Zdefiniuj punkty końcowe powiadomień

  • Jakie usługi są używane do wysyłania wiadomości
  • Jakie informacje zwrotne / potwierdzenia są przekazywane (synchronizacja / asynchronizacja)
  • Czy to możliwe, aby dodać nowe punkty końcowe [nawet jeśli tak, to czy to nawet wymaga abstrakcji]

Waham się, czy podać konkretny przykład architektury, ponieważ byłby on w dużej mierze zależny od czynników; ale często najprostsze systemy komunikatów obejmują podstawową kolejkę, albo w pamięci / aplikacji, bez SQL, na dysku lub w relacyjnej bazie danych. Następnie osobny proces (lub kilka oddzielnych procesów, jeśli są rozproszone) może sondować kolejkę pod kątem typów komunikatów [tj. Zadanie cron]; i wysłać w razie potrzeby.

Można to również ulepszyć za pomocą niektórych technik opartych na wypychaniu (tj. NOTGY / LISTEN PostgreSQL), jeśli istnieje konieczność natychmiastowego wysłania wiadomości.

Zaletą prostej kolejki jest to, że system generujący komunikat ma niewiele do zrobienia, a system przetwarzania może być zrównoważony w oparciu o wymagania sprzętowe / wydajnościowe.

nathan-m
źródło
bardzo dziękuję za szczegóły odpowiedzi, które faktycznie pomagają mi mieć jaśniejsze pomysły. Zredagowałem swoją odpowiedź, aby odpowiedzieć na postawione pytania.
Trent
-2

Czy bierzesz pod uwagę wzorzec projektowy wagi latania dla obiektów powiadomień? Nie jestem tego zbyt pewny, ponieważ nigdy nie wdrożyłem wzoru, ale przypominam sobie, że wiąże się to z dzieleniem pewnego stanu między obiektami typu flyweight. Myślę też, że członkowie z większą redundancją mieli większy wpływ, jeśli zostali podzieleni. Zależy to więc od wysłania kilku wiadomości do wielu osób lub odwrotnie.

Christoph
źródło