Sposób, w jaki robi to Facebook, jest dość interesujący.
Powszechną metodą wykonywania takich powiadomień jest odpytywanie skryptu na serwerze (za pomocą AJAX) w danym przedziale czasowym (być może co kilka sekund), aby sprawdzić, czy coś się stało. Jednak może to być dość intensywne dla sieci i często wysyłasz bezcelowe żądania, ponieważ nic się nie wydarzyło.
Sposób, w jaki robi to Facebook, wykorzystuje podejście kometowe, zamiast sondować interwał, gdy tylko jedna ankieta się zakończy, wydaje kolejną. Jednak każde żądanie do skryptu na serwerze ma bardzo długi limit czasu, a serwer odpowiada na żądanie tylko wtedy, gdy coś się wydarzyło. Możesz to zobaczyć, jeśli otworzysz kartę Konsoli Firebuga na Facebooku, a prośby o skrypt mogą potrwać kilka minut. Jest to naprawdę genialne, ponieważ metoda ta natychmiast zmniejsza zarówno liczbę żądań, jak i częstotliwość ich wysyłania. Teraz efektywnie masz strukturę zdarzeń, która pozwala serwerowi „odpalać” zdarzenia.
Za tym, pod względem faktycznej zawartości zwracanej z tych ankiet, jest odpowiedź JSON, z czymś, co wydaje się być listą zdarzeń i informacjami o nich. Jest jednak zminimalizowany, więc jest trochę trudny do odczytania.
Jeśli chodzi o rzeczywistą technologię, AJAX to sposób, aby przejść tutaj, ponieważ możesz kontrolować limity czasu żądań i wiele innych rzeczy. Polecam (tutaj stos przelewu przepełnienia) przy użyciu jQuery do AJAX, zajmie to wiele problemów związanych z kompatybilnością. Jeśli chodzi o PHP, możesz po prostu sondować tabelę bazy danych dziennika zdarzeń w swoim skrypcie PHP i powrócić do klienta tylko wtedy, gdy coś się stanie? Oczekuję, że istnieje wiele sposobów realizacji tego.
Realizowanie:
Po stronie serwera:
Wydaje się, że jest kilka implementacji bibliotek komet w PHP, ale szczerze mówiąc, jest to naprawdę bardzo proste, być może coś w rodzaju następującego pseudokodu:
while(!has_event_happened()) {
sleep(5);
}
echo json_encode(get_events());
Funkcja has_event_happened sprawdziłaby tylko, czy coś się wydarzyło w tabeli zdarzeń lub coś, a następnie funkcja get_events zwróciłaby listę nowych wierszy w tabeli? Naprawdę zależy od kontekstu problemu.
Nie zapomnij zmienić maksymalnego czasu wykonywania PHP, w przeciwnym razie upłynie limit czasu wcześniej!
Strona klienta:
Spójrz na wtyczkę jQuery do interakcji z kometą:
To powiedziawszy, wtyczka wydaje się nieco bardziej złożona, jest naprawdę bardzo prosta na kliencie, być może (z jQuery) coś takiego:
function doPoll() {
$.get("events.php", {}, function(result) {
$.each(result.events, function(event) { //iterate over the events
//do something with your event
});
doPoll();
//this effectively causes the poll to run again as
//soon as the response comes back
}, 'json');
}
$(document).ready(function() {
$.ajaxSetup({
timeout: 1000*60//set a global AJAX timeout of a minute
});
doPoll(); // do the first poll
});
Wszystko zależy w dużej mierze od tego, jak tworzona jest twoja architektura.
Aktualizacja
Ponieważ nadal otrzymuję opinie na ten temat, myślę, że rozsądnie jest pamiętać, że ta odpowiedź ma 4 lata. Sieć rozwija się w naprawdę szybkim tempie, więc proszę uważaj na tę odpowiedź.
Ostatnio miałem ten sam problem i szukałem informacji na ten temat.
Podane rozwiązanie nazywa się długim odpytywaniem. Aby poprawnie z niego korzystać, należy upewnić się, że żądanie AJAX ma „duży” limit czasu i zawsze wysyłać to żądanie po bieżącym zakończeniu (limit czasu, błąd lub sukces).
Long Polling - Klient
Tutaj, aby kod był krótki, użyję jQuery:
Ważne jest, aby pamiętać, że (z dokumentów jQuery ):
Długie odpytywanie - serwer
Nie jest w żadnym konkretnym języku, ale wyglądałoby to tak:
Tutaj
hasTimedOut
upewni się, że Twój kod nie czeka wiecznie, ianythingHappened
sprawdzi, czy jakieś zdarzenie się wydarzyło. Masleep
to na celu uwolnienie twojego wątku do robienia innych rzeczy, gdy nic się nie dzieje.events
Powróci słownika zdarzeń (lub jakiekolwiek inne struktury danych może wolisz) w formacie JSON (lub innego wolisz).To z pewnością rozwiązuje problem, ale jeśli martwisz się skalowalnością i wydajnością, tak jak ja podczas badań, możesz rozważyć inne rozwiązanie, które znalazłem.
Rozwiązanie
Użyj gniazd!
Po stronie klienta, aby uniknąć problemów ze zgodnością, użyj socket.io . Próbuje używać gniazda bezpośrednio i ma awarie innych rozwiązań, gdy gniazda nie są dostępne.
Po stronie serwera utwórz serwer za pomocą NodeJS (przykład tutaj ). Klient zasubskrybuje ten kanał (obserwator) utworzony za pomocą serwera. Za każdym razem, gdy trzeba wysłać powiadomienie, jest ono publikowane na tym kanale, a subskrybor (klient) zostaje powiadomiony.
Jeśli nie podoba ci się to rozwiązanie, wypróbuj APE ( Ajax Push Engine ).
Mam nadzieję, że pomogłem.
źródło
hasTimedOut()
?Według pokazu slajdów na temat systemu wiadomości Facebooka, Facebook używa technologii kometowej do „wypychania” wiadomości do przeglądarek internetowych. Serwer komet Facebooka jest zbudowany na otwartym serwerze internetowym Erlang mochiweb.
Na poniższym obrazku wyrażenie „klastry kanałów” oznacza „serwery komet”.
Wiele innych dużych witryn buduje własny serwer komet, ponieważ istnieją różnice między potrzebami każdej firmy. Ale zbudowanie własnego serwera komet na otwartym serwerze komet jest dobrym podejściem.
Możesz wypróbować icomet , serwer komet C1000K C ++ zbudowany z libevent. icomet zapewnia również bibliotekę JavaScript, jest łatwy w użyciu tak prosty jak:
icomet obsługuje szeroki zakres przeglądarek i systemów operacyjnych, w tym Safari (iOS, Mac), IE (Windows), Firefox, Chrome itp.
źródło
Facebook używa MQTT zamiast HTTP. Push jest lepszy niż odpytywanie. Poprzez HTTP musimy stale odpytywać serwer, ale poprzez serwer MQTT przekazuje wiadomość do klientów.
Porównanie MQTT i HTTP: http://www.youtube.com/watch?v=-KNPXPmx88E
Uwaga: moje odpowiedzi najlepiej pasują do urządzeń mobilnych.
źródło
Jednym z ważnych problemów z długim odpytywaniem jest obsługa błędów. Istnieją dwa rodzaje błędów:
Żądanie może przekroczyć limit czasu, w którym to przypadku klient powinien natychmiast ponownie nawiązać połączenie. Jest to normalne zdarzenie przy długim odpytywaniu, gdy nie nadeszły żadne wiadomości.
Błąd sieci lub błąd wykonania. Jest to rzeczywisty błąd, który klient powinien z wdzięcznością zaakceptować i poczekać, aż serwer powróci on-line.
Głównym problemem jest to, że jeśli moduł obsługi błędów natychmiast ponownie ustanowi połączenie również w przypadku błędu typu 2, klienci prześlą serwer DOS na serwer.
Obie odpowiedzi z przykładowym kodem tego brakuje.
źródło