Obecnie pracuję nad projektem Ruby on Rails , który pokazuje listę obrazów.
Niezbędnym elementem tego projektu jest to, że pokazuje on nowe posty w czasie rzeczywistym bez konieczności odświeżania strony internetowej. Po pewnym czasie natknąłem się na niektóre rozwiązania i usługi JavaScript, takie jak PubNub; jednak żadne z dostarczonych rozwiązań w ogóle nie miało sensu.
W rozwiązaniu JavaScript ( odpytywanie ) dzieje się:
- Użytkownik 1 wyświetla listę zdjęć.
- W tle kod JavaScript odpytuje punkt końcowy co sekundę, aby sprawdzić, czy jest nowy post.
- Użytkownik 2 dodaje nowe zdjęcie.
- Wystąpiło opóźnienie 50 ms przed uruchomieniem nowego cyklu i pobraniem nowych danych.
- Nowa zawartość jest ładowana do DOM .
Wydaje się to dziwne w tłumaczeniu na przykład z prawdziwego świata:
- Użytkownik 1 trzyma stos zdjęć na swoim biurku.
- Co sekundę podchodzi do fotografa i pyta, czy ma nowego.
- Fotograf robi nowe zdjęcie.
- W tym momencie, gdy on / ona wchodzi, może zrobić zdjęcie i położyć je na stosie.
Moim zdaniem rozwiązanie powinno wyglądać następująco:
- Użytkownik 1 trzyma stos zdjęć na swoim biurku.
- Fotograf robi nowe zdjęcie.
- Fotograf podchodzi do stosu i kładzie go z resztą.
Rozwiązanie PubNub jest w zasadzie takie samo, jednak tym razem między stronami chodzi stażysta, aby udostępnić dane.
Nie trzeba dodawać, że oba rozwiązania są bardzo energochłonne, ponieważ uruchamiane są nawet wtedy, gdy nie ma danych do załadowania.
O ile mi wiadomo, nie ma (logicznego) wyjaśnienia, dlaczego ten sposób implementacji jest stosowany w prawie każdej aplikacji w czasie rzeczywistym.
Odpowiedzi:
Pushing działa dobrze dla 1 lub ograniczonej liczby użytkowników.
Teraz zmień scenariusz z jednym fotografem i 1000 użytkowników, którzy chcą kopii tego zdjęcia. Fotograf będzie musiał przejść do 1000 stosów. Niektóre z nich mogą znajdować się w zamkniętym biurze lub rozrzucone po całej podłodze. Lub ich użytkownik na wakacjach i brak zainteresowania w tej chwili nowymi zdjęciami.
Fotograf byłby cały czas zajęty spacerowaniem i nie robiłby nowych zdjęć.
Zasadniczo: model ściągania / odpytywania lepiej skaluje się do wielu niewiarygodnych czytelników z luźnymi wymaganiami w czasie rzeczywistym (jeśli zdjęcie zajmie 10 sekund później, aby dotrzeć na stos, co jest wielka sprawa).
To powiedziawszy, model push jest wciąż lepszy w wielu sytuacjach. Jeśli potrzebujesz małego opóźnienia (potrzebujesz tego nowego zdjęcia po 5 sekundach) lub aktualizacje są rzadkie, a prośby są częste i przewidywalne (pytaj fotografa co 10 sekund, kiedy generuje nowe zdjęcie dziennie), wtedy ciągnięcie jest nieodpowiednie. To zależy od tego, co próbujesz zrobić. NASDAQ: push. Serwis pogodowy: ciągnij. Fotograf ślubny: prawdopodobnie pociągnij. News agencja fotograficzna: prawdopodobnie push.
źródło
Jestem naprawdę zaskoczony, że tylko jedna osoba wspomniała o WebSockets . Wsparcie jest realizowane w zasadzie w każdej dużej przeglądarce .
W rzeczywistości PubNub ich używa. W przypadku Twojej aplikacji przeglądarka prawdopodobnie zasubskrybuje gniazdo, które będzie nadawać, gdy tylko będzie dostępne nowe zdjęcie. Pamiętaj, że gniazdo nie wyśle zdjęcia, ale tylko link, aby przeglądarka mogła pobrać je asynchronicznie.
W twoim przykładzie wyobraź sobie coś takiego:
To jest trochę jak twoje oryginalne przykładowe rozwiązanie. Jest to bardziej wydajne niż odpytywanie, ponieważ klient nie musi wysyłać żadnych danych do serwera (może z wyjątkiem uderzeń serca ).
Ponadto, jak wspomniano inni, istnieją inne metody, które są lepsze niż proste odpytywanie, które działają w starszych przeglądarkach ( longpolling, i in .)
źródło
StackExchange
witryny takie jak ta, w której aktualnie się znajdujesz (chyba że patrzysz na tę stronę zapisaną w pamięci podręcznej / zapisaną)WebSockets
. Właśnie dlatego zastanawiałem się, dlaczego nikt nie wspomniał o @korylprinceWebSockets
.Czasami wystarczająco dobry jest wystarczająco dobry.
Ze wszystkich możliwych sposobów wdrożenia procesu komunikacji „w czasie rzeczywistym” odpytywanie jest być może najprostszym sposobem. Odpytywanie można efektywnie wykorzystać, gdy interwał odpytywania jest stosunkowo długi (tj. Sekundy, minuty lub godziny zamiast chwilowe), a cykle zegara zużywane przez sprawdzanie połączenia lub zasobu tak naprawdę nie mają znaczenia.
źródło
Protokół HTTP jest ograniczony, ponieważ klient MUSI być tym, który inicjuje żądanie. Serwer nie może komunikować się z klientem, chyba że odpowie na żądanie klienta.
Aby dostosować przykład ze świata rzeczywistego, dodaj następujące ograniczenie:
Z tym nowym ograniczeniem, jak zrobiłbyś to inaczej niż ankietowanie?
źródło
Dlaczego ankiety są akceptowane? Ponieważ w rzeczywistości każde rozwiązanie jest odpytywaniem niskiego poziomu!
Jeśli serwer powinien cię zaktualizować, gdy tylko pojawią się nowe zdjęcia, zwykle musi mieć połączenie z tobą - ponieważ adresy IP często się zmieniają i nigdy nie wiesz, czy ktoś nie jest już zainteresowany, więc klient musi wysłać jakąś formę sygnał utrzymania, na przykład: „Nadal tu jestem, nie jestem offline”
Wszystkie połączenia stanowe (na przykład TCP / IP) działają tak samo, ponieważ można wysyłać tylko pojedyncze pakiety danych przez Internet; nigdy nie wiadomo, czy druga strona nadal tam jest.
Tak więc każdy protokół ma limit czasu. Jeśli istota nie odpowie w ciągu X sekund, zakłada się, że jest martwa. Więc nawet jeśli masz tylko otwarte połączenie między serwerem a klientem, bez wysyłania żadnych danych, serwer i klient muszą wysyłać regularne pakiety utrzymywania aktywności (jest to obsługiwane na niskim poziomie, jeśli otworzysz połączenie między nimi) - i jak to zrobić to w końcu różni się od ankiet?
Zatem najlepszym podejściem byłoby prawdopodobnie długotrwałe zbieranie:
Klient wysyła żądanie natychmiast po załadowaniu strony (na przykład mówiąc fotografowi „Powiedz mi, czy są jakieś nowe zdjęcia”), ale serwer nie odpowiada, jeśli nie ma żadnych nowych zdjęć. Gdy tylko upłynie limit czasu, klient pyta ponownie.
Jeśli serwer ma teraz nowe zdjęcia, może natychmiast odpowiedzieć wszystkim klientom stojącym w kolejce po nowe zdjęcia. Twój czas reakcji po nowym zdjęciu jest nawet krótszy niż w przypadku wypychania, ponieważ klient nadal czeka w otwartym połączeniu na odpowiedź i nie musisz nawiązywać połączenia z klientem. A żądania odpytywania od klienta nie są znacznie większym ruchem niż stałe połączenie między klientem a serwerem w celu uzyskania odpowiedzi!
źródło
Jedną z zalet sondowania jest to, że ogranicza szkodę, która może być spowodowana brakiem wiadomości lub usterką stanu. Jeśli X pyta Y o swój stan co pięć sekund, wówczas utrata żądania lub odpowiedzi spowoduje jedynie, że informacja X będzie o dziesięć sekund nieaktualna, a nie 5. Jeśli Y zostanie ponownie uruchomiony, X może dowiedzieć się o tym następnego czas Y jest w stanie odpowiedzieć na jeden z komunikatów X. Jeśli X zostanie zrestartowany, może nigdy nie zadać sobie trudu, by poprosić Y o cokolwiek później, ale ktokolwiek obserwuje status X, powinien rozpoznać, że został zrestartowany.
Jeśli zamiast X odpytujący Y, X polegał na Y, aby poinformować go za każdym razem, gdy zmienił się jego stan, to jeśli stan Y zmienił się i wysłał wiadomość do X, ale z jakiegokolwiek powodu wiadomość ta nie została odebrana, X może nigdy nie być świadomy zmiany . Podobnie, jeśli Y zostanie ponownie uruchomiony i nigdy nie ma powodu, aby wysyłać X wiadomość o czymkolwiek.
W niektórych przypadkach może być pomocne, aby X zażądał, aby Y autonomicznie wysyłał wiadomości o swoim statusie, albo okresowo, albo gdy się zmienia, i miałby sondowanie X tylko, jeśli trwa zbyt długo, nie słysząc nic od Y. Taki projekt może wyeliminować potrzeba, aby X wysłał większość swoich wiadomości (zwykle X powinien przynajmniej od czasu do czasu poinformować Y, że nadal jest zainteresowany otrzymywaniem wiadomości, i Y powinien przestać wysyłać wiadomości, jeśli trwa zbyt długo bez żadnego zainteresowania). Taki projekt wymagałby jednak Y, aby uporczywiezachowują informacje o X, zamiast móc po prostu wysłać odpowiedź temu, kto sondował, a następnie natychmiast zapomnieć o tym, kto to był. Jeśli Y jest systemem wbudowanym, takie uproszczenie może pomóc w wystarczającym zmniejszeniu wymagań dotyczących pamięci, aby umożliwić użycie mniejszego i tańszego kontrolera.
Sondowanie może mieć dodatkową zaletę w przypadku korzystania z potencjalnie zawodnego medium komunikacyjnego (np. UDP lub radia): może w dużej mierze wyeliminować potrzebę potwierdzania warstwy łącza. Jeśli X wysyła Y żądanie statusu Q, Y odpowiada raportem statusu R, a X słyszy R, X nie będzie musiał słyszeć żadnego potwierdzenia warstwy łącza, aby Q wiedział, że zostało odebrane. I odwrotnie, gdy Y wyśle R, nie musi wiedzieć ani przejmować się, czy X go otrzymał. Jeśli X wyśle żądanie statusu i nie otrzyma odpowiedzi, może wysłać kolejne. Jeśli Y wyśle raport, a X go nie usłyszy, X wyśle kolejne żądanie. Jeśli każde żądanie zniknie raz i albo da odpowiedź, albo nie, żadna ze stron nie musi wiedzieć ani przejmować się, czy dana wiadomość została odebrana. Ponieważ wysłanie potwierdzenia może zająć prawie tyle samo przepustowości, co żądanie statusu lub raport, korzystanie z raportu z prośbą w obie strony nie kosztuje dużo więcej niż niezamówiony raport i potwierdzenie. Jeśli X wyśle kilka żądań bez otrzymania odpowiedzi, może w niektórych sieciach z routingiem dynamicznym musi włączyć potwierdzenia na poziomie łącza (i poprosić w swoim żądaniu, aby Y zrobił to samo), aby stos protokołu protokołu mógł rozpoznać problem z dostarczeniem i wyszukać nowa trasa, ale gdy wszystko działa, model zgłoszeń-żądań będzie bardziej wydajny niż stosowanie potwierdzeń na poziomie łącza.
źródło
Pytanie polega na zbilansowaniu liczby niepotrzebnych ankiet względem liczby niepotrzebnych wypychań.
Jeśli sondujesz:
Jeśli naciskasz:
Istnieje kilka rozwiązań dotyczących radzenia sobie z różnymi scenariuszami i ich wadami, takich jak na przykład minimalny czas między sondażami, serwery proxy tylko do sondowania, aby zdjąć obciążenie z głównego systemu, lub - w przypadku wypchnięć - rozporządzenie rejestrujące i określające pożądane dane, a następnie wyrejestrowanie podczas wylogowywania. To, które najlepiej pasuje, nie jest ogólnie rzecz biorąc możliwe do powiedzenia, zależy to od systemu.
W twoim przykładzie odpytywanie nie jest najbardziej wydajnym rozwiązaniem, ale najbardziej praktycznym. Bardzo łatwo jest napisać system odpytywania w JavaScript i bardzo łatwo wdrożyć go również po stronie dostawy. Serwer stworzony do dostarczania danych obrazu powinien być w stanie obsłużyć dodatkowe żądania, a jeśli nie, może być skalowany liniowo, ponieważ dane są w większości statyczne i dlatego mogą być łatwo buforowane.
Metoda wypychania implementująca logowanie, opis potrzebnych danych i wreszcie wylogowanie byłaby najbardziej wydajna, ale prawdopodobnie jest zbyt złożona dla przeciętnego „skrypciarza” i musi poradzić sobie z pytaniem: co jeśli użytkownik po prostu wyłącza przeglądarkę i nie można się wylogować?
Może lepiej jest mieć więcej użytkowników (ponieważ dostęp jest łatwy) niż zaoszczędzić trochę pieniędzy na innym serwerze pamięci podręcznej?
źródło
Z jakiegoś powodu w dzisiejszych czasach wydaje się, że wszyscy młodsi programiści zapomnieli lekcji z przeszłości i dlaczego niektóre rzeczy ewoluowały w taki sposób.
W obliczu tych ograniczeń możesz nie mieć stałej komunikacji dwukierunkowej. A jeśli spojrzysz na model OSI, przekonasz się, że większość rozważań ma na celu oddzielenie trwałości od podstawowego połączenia.
Mając to na uwadze, metoda pobierania informacji przez sondowanie jest doskonałym sposobem na zmniejszenie przepustowości i obliczeń po stronie klienta. Wzrost push jest tak naprawdę w przeważającej części tylko tym, że klient dokonuje ciągłego odpytywania lub gniazd sieciowych. Osobiście, gdybym był tam wszystkim, doceniłbym regularność odpytywania jako środka analizy ruchu, w którym przekroczenie czasu żądania GET / POST zasygnalizowałoby mężczyznę w jakiejś środkowej sytuacji.
źródło