Powszechnym podejściem, jak już wspomniano Ozz , jest kolejka komunikatów . Z perspektywy projektowej kolejka komunikatów jest zasadniczo kolejką FIFO , która jest raczej podstawowym typem danych:
Tym, co sprawia, że kolejka komunikatów jest wyjątkowa, jest to, że chociaż twoja aplikacja jest odpowiedzialna za kolejkowanie, inny proces byłby odpowiedzialny za de-kolejkowanie. W kolejce lingo aplikacja jest nadawcą wiadomości, a proces usuwania z kolejki jest odbiorcą. Oczywistą zaletą jest to, że cały proces jest asynchroniczny, odbiorca działa niezależnie od nadawcy, o ile istnieją komunikaty do przetworzenia. Oczywistą wadą jest to, że potrzebujesz dodatkowego komponentu, nadawcy, aby całość działała.
Ponieważ twoja architektura opiera się teraz na dwóch komponentach wymieniających wiadomości, możesz użyć do tego fantazyjnego terminu komunikacji międzyprocesowej .
W jaki sposób wprowadzenie kolejki wpływa na projekt aplikacji?
Niektóre działania w aplikacji generują wiadomości e-mail. Wprowadzenie kolejki komunikatów oznaczałoby, że te akcje powinny teraz wypychać wiadomości do kolejki (i nic więcej). Wiadomości te powinny zawierać absolutnie minimalną ilość informacji niezbędnych do zbudowania wiadomości e-mail, gdy odbiorca je przetworzy.
Format i treść wiadomości
Format i treść wiadomości zależy wyłącznie od Ciebie, ale należy pamiętać, że im mniejsze, tym lepiej. Twoja kolejka powinna być zapisywana i przetwarzana tak szybko, jak to możliwe, a rzucenie na nią dużej ilości danych prawdopodobnie stworzy wąskie gardło.
Ponadto kilka usług kolejkowania opartych na chmurze ma ograniczenia dotyczące rozmiarów wiadomości i może dzielić większe wiadomości. Nie zauważysz, podzielone wiadomości będą podawane jako jedna, gdy o nie poprosisz, ale zostaniesz obciążony za wiele wiadomości (zakładając oczywiście, że korzystasz z usługi, która wymaga opłaty).
Konstrukcja odbiornika
Ponieważ mówimy o aplikacji internetowej, powszechnym podejściem dla twojego odbiornika byłby prosty skrypt cron. Działa co x
minutę (lub sekundy) i:
- Pop
n
ilość wiadomości z kolejki,
- Przetwarzaj wiadomości (tj. Wysyłaj wiadomości e-mail).
Zauważ, że mówię „pop” zamiast „pobierz” lub „pobierz”, ponieważ odbiorca nie tylko pobiera elementy z kolejki, ale także je usuwa (tj. Usuwa je z kolejki lub oznacza jako przetworzone). To, jak dokładnie to nastąpi, zależy od implementacji kolejki komunikatów i specyficznych potrzeb aplikacji.
Oczywiście to, co opisuję, jest zasadniczo operacją wsadową , najprostszym sposobem przetwarzania kolejki. W zależności od potrzeb możesz chcieć przetwarzać wiadomości w bardziej skomplikowany sposób (wymagałoby to również bardziej skomplikowanej kolejki).
ruch drogowy
Twój odbiornik może wziąć pod uwagę ruch i dostosować liczbę przetwarzanych wiadomości na podstawie ruchu w czasie jego działania. Uproszczone podejście polegałoby na przewidywaniu godzin intensywnego ruchu na podstawie przeszłych danych o ruchu i przy założeniu, że korzystasz ze skryptu cron, który uruchamia się co x
minutę, możesz zrobić coś takiego:
if(
now() > 2pm && now() < 7pm
) {
process(10);
} else {
process(100);
}
function process(count) {
for(i=0; i<=count; i++) {
message = dequeue();
mail(message)
}
}
Bardzo naiwne i brudne podejście, ale działa. Jeśli tak się nie stanie, drugim podejściem byłoby sprawdzenie aktualnego ruchu serwera na każdej iteracji i odpowiednie dostosowanie liczby elementów procesu. Nie dokonuj mikrooptymalizacji, jeśli nie jest to absolutnie konieczne, tracisz czas.
Miejsce w kolejce
Jeśli Twoja aplikacja korzysta już z bazy danych, najprostszym rozwiązaniem będzie pojedyncza tabela na niej:
CREATE TABLE message_queue (
id int(11) NOT NULL AUTO_INCREMENT,
timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
processed enum('0','1') NOT NULL DEFAULT '0',
message varchar(255) NOT NULL,
PRIMARY KEY (id),
KEY timestamp (timestamp),
KEY processed (processed)
)
To naprawdę nie jest bardziej skomplikowane. Możesz oczywiście uczynić to tak skomplikowanym, jak potrzebujesz, możesz na przykład dodać pole priorytetowe (co oznaczałoby, że nie jest to już kolejka FIFO, ale jeśli naprawdę jej potrzebujesz, kogo to obchodzi?). Możesz również uprościć to, pomijając przetworzone pole (ale wtedy będziesz musiał usunąć wiersze po ich przetworzeniu).
Tabela bazy danych byłaby idealna dla 2000 wiadomości dziennie, ale prawdopodobnie nie byłaby dobrze skalowana dla milionów wiadomości dziennie. Należy wziąć pod uwagę milion czynników, wszystko w twojej infrastrukturze odgrywa rolę w ogólnej skalowalności twojej aplikacji.
W każdym razie, zakładając, że już zidentyfikowałeś kolejkę opartą na bazie danych jako wąskie gardło, następnym krokiem byłoby przyjrzenie się usłudze opartej na chmurze. Amazon SQS to jedyna usługa, z której korzystałem i zrobił to, co obiecał. Jestem pewien, że istnieje wiele podobnych usług.
Kolejki oparte na pamięci również należy rozważyć, szczególnie w przypadku kolejek krótkotrwałych. memcached doskonale nadaje się do przechowywania w kolejce wiadomości.
Niezależnie od miejsca, w którym zdecydujesz się zbudować kolejkę, bądź sprytny i abstrakcyjny. Ani nadawca, ani odbiorca nie powinni być przywiązani do konkretnego magazynu, w przeciwnym razie przejście na inny magazyn w późniejszym czasie byłoby kompletną PITA.
Prawdziwe podejście do życia
Zbudowałem kolejkę wiadomości e-mail, która jest bardzo podobna do tego, co robisz. To było na projekcie PHP i zbudowałem go wokół Zend Queue , komponentu Zend Framework, który oferuje kilka adapterów do różnych magazynów. Moje magazyny, w których:
- Tablice PHP do testowania jednostkowego,
- Amazon SQS w produkcji,
- MySQL w środowisku programistycznym i testowym.
Moje wiadomości były tak proste, jak tylko mogą być, moja aplikacja utworzyła małe tablice z niezbędnymi informacjami ( [user_id, reason]
). Magazyn komunikatów był serializowaną wersją tej tablicy (najpierw był to wewnętrzny format serializacji PHP, potem JSON, nie pamiętam, dlaczego się zmieniłem). reason
Jest stała i oczywiście mam duży gdzieś tabeli, który mapuje reason
do pełniejszych wyjaśnień (I udało się wysłać e-maile do około 500 klientów z tajemniczy reason
zamiast pełniejszego wiadomości raz).
Dalsza lektura
Standardy:
Przybory:
Ciekawe czyta: