Długie ankiety / Streaming HTTP Ogólne pytania

Próbuję stworzyć teoretyczną aplikację do czatu internetowego z php i jquery , czytałem o długich ankietach i streamingu http i udało mi się zastosować większość zasad wprowadzonych w artykułach. Jednak są 2 główne rzeczy, których wciąż nie mogę ogarnąć.

Z Długim Sondażem

  • skąd serwer będzie wiedział o wysłaniu aktualizacji? czy będzie musiał ciągle sprawdzać bazę danych, czy jest lepszy sposób?

Z HTTP Streaming

  • Jak sprawdzić wyniki podczas połączenia Ajax jest nadal aktywny? Jestem świadomy funkcji jQuery success dla połączeń ajax, ale jak sprawdzić dane gdy połączenie jest nadal w toku?
Będę wdzięczny za wszelkie odpowiedzi, z góry dzięki.
Author: Madara Uchiha, 2011-08-27

2 answers

Tak, techniki przypominające komety Zwykle wysadzają mózg na początku, sprawiając, że myślisz w inny sposób. I kolejny problem jest taki, że nie ma zbyt wielu zasobów dostępnych dla PHP, bo każdy robi swoją kometę w node.js, Python, Java itp.

Postaram się odpowiedzieć na twoje pytania, mam nadzieję, że rzuci to trochę światła na ten temat dla ludzi.

Skąd serwer będzie wiedział o wysłaniu aktualizacji? czy będzie musiał ciągle sprawdzać bazę danych czy jest jest lepszy sposób?

Odpowiedź brzmi: w najbardziej ogólnym przypadku należy użyć kolejki komunikatów (mq). RabbitMQ lub funkcjonalność Pub/Sub wbudowana w sklep Redis może być dobrym wyborem, choć na rynku dostępnych jest wiele konkurencyjnych rozwiązań, takich jak ZeroMQ, Beanstalkd itp.

Więc zamiast ciągłego przeszukiwania bazy danych, możesz po prostu subskrybować dla zdarzenia MQ i po prostu czekać, aż ktoś inny opublikuje wiadomość, którą subskrybowałeś a MQ cię obudzi i wyśle wiadomość. Aplikacja do czatu jest bardzo dobrym przykładem użycia, aby zrozumieć tę funkcjonalność.

Muszę również wspomnieć, że jeśli szukałbyś implementacji Comet-chat w innych językach, mógłbyś zauważyć proste, nie używające MQ. Więc jak wymieniają się informacjami? Chodzi o to, że takie rozwiązania są zazwyczaj implementowane jako samodzielne jednowątkowe serwery asynchroniczne, więc mogą przechowywać wszystkie połączenia w Lokalnej Tablicy wątku (lub coś podobne), obsługuje wiele połączeń w jednej pętli i po prostu wybierz jeden i powiadom w razie potrzeby. Takie asynchroniczne implementacje serwerów to nowoczesne podejście, które świetnie pasuje do techniki komety. Jednak najprawdopodobniej implementujesz swoją kometę na mod_php lub FastCGI, w tym przypadku to proste podejście nie jest dla Ciebie opcją i powinieneś użyć MQ.

Może to być nadal bardzo przydatne, aby zrozumieć, jak zaimplementować autonomiczny asynchroniczny Serwer Comet do obsługi wielu połączenia w jednym wątku. Najnowsze wersje PHP obsługują strumienie Libevent i Socket, dzięki czemu możliwe jest zaimplementowanie tego typu serwera również w PHP. Istnieje również przykład dostępny w dokumentacji PHP.

Jak sprawdzić wyniki podczas połączenia Ajax jest nadal aktywny? Jestem świadomy funkcji sukcesu jQuery dla połączeń ajax, ale jak sprawdzić dane, gdy połączenie jest nadal w toku?

Jeśli robisz swoje długie ankiety z użyciem zwykłej techniki Ajax takiej jak plain XHR, Jquery Ajax itp. nie masz łatwego sposobu przesyłania kilku odpowiedzi w jednym żądaniu Ajax. Jak wspomniałeś, masz tylko "sukces", aby poradzić sobie z odpowiedzią w całości, a nie z jej częścią. W ramach obejścia problemu ludzie wysyłają tylko jedną odpowiedź na żądanie i przetwarzają ją w programie obsługi "sukcesu", po czym po prostu otwierają nowe żądanie z długą ankietą. Tak właśnie działa protokół HTTP.

Należy również wspomnieć, że w rzeczywistości istnieją obejścia do zaimplementowania funkcjonalności podobnej do przesyłania strumieniowego przy użyciu różnych technik, takich jak nieskończenie długa strona w ukrytym IFRAME lub przy użyciu wieloczęściowych odpowiedzi HTTP. Obie te metody są pewne wady (pierwsza jest uważana za zawodną i czasami może powodować niechciane zachowanie przeglądarki, takie jak nieskończony wskaźnik ładowania, a druga przecieka spójna i prosta obsługa między przeglądarkami, jednak niektóre aplikacje nadal są znane skutecznie polegają na tym, że mechanizm wraca do długiego sondowania, gdy przeglądarka nie może poprawnie obsłużyć odpowiedzi wieloczęściowych).

Jeśli chcesz obsługiwać wiele odpowiedzi na jedno żądanie/połączenie w niezawodny sposób, powinieneś rozważyć użycie bardziej zaawansowanej technologii, takiej jak WebSocket, która jest obsługiwana przez najbardziej aktualne przeglądarki lub na dowolnej platformie obsługującej surowe gniazda (takie jak Flash lub jeśli tworzysz na przykład aplikację mobilną).

Czy mógłbyś rozwiń więcej na temat kolejek wiadomości?

Kolejka komunikatów to termin opisujący samodzielną (lub wbudowaną) implementację wzorca obserwatora (znanego również jako "Publish/Subscribe" lub po prostu PubSub). Jeśli tworzysz dużą aplikację, jej posiadanie jest bardzo użyteczne -- pozwala oddzielić różne części systemu, zaimplementować asynchroniczny projekt oparty na zdarzeniach i znacznie ułatwić Ci życie, szczególnie w heterogenicznych systemach. Ma wiele aplikacje do systemów świata rzeczywistego, wspomnę tylko o kilku z nich:

  • kolejki zadań. Załóżmy, że piszemy własne YouTube i musimy przekonwertować pliki wideo użytkowników w tle. Oczywiście powinniśmy mieć webapp z interfejsem użytkownika, aby przesłać film i pewną stałą liczbę procesów roboczych do konwersji plików wideo(może nawet potrzebujemy kilku dedykowanych serwerów, na których tylko nasi pracownicy opuszczą). Również prawdopodobnie musielibyśmy napisać naszych pracowników w C, aby zapewnić lepsza wydajność. Wszystko, co musimy zrobić, to po prostu skonfigurować serwer kolejki wiadomości, aby zbierać i dostarczać zadania konwersji wideo z webapp do naszych pracowników. Gdy robotnik się pojawi, łączy się z MQ i bezczynnie czeka na nowe zadania. Gdy ktoś przesyła plik wideo webapp łączy się z MQ i publikuje wiadomość z nowym zadaniem. Potężne mq, takie jak RabbitMQ mogą równomiernie rozdzielać zadania między liczbę połączonych pracowników, śledzić, jakie zadania zostały wykonane, zapewnić nic nie zostanie utracone i zapewni fail-over, a nawet admin UI do przeglądania bieżących zadań i statystyk.
  • asynchroniczne zachowanie. Nasz Comet-chat jest dobrym przykładem. Oczywiście nie chcemy okresowo przeszukiwać naszej bazy danych przez cały czas (po co więc Kometa? -- Nie duża różnica w wykonywaniu cyklicznych żądań Ajax). Wolelibyśmy, aby ktoś nas powiadomił, gdy pojawi się nowa wiadomość na czacie. A kolejka komunikatów to ten ktoś. Powiedzmy, że używamy Redis klucz / wartość store -- jest to naprawdę świetne narzędzie, które zapewnia pubsub implementację wśród swoich funkcji przechowywania danych. Najprostszy scenariusz może wyglądać następująco:
    1. Po tym, jak ktoś wejdzie do czatu, powstaje nowa Prośba o długą ankietę Ajax.
    2. obsługa żądań po stronie serwera wydaje polecenie Redis, aby SUBSKRYBOWAĆ KANAŁ 'newmessage'.
    3. gdy ktoś wprowadzi wiadomość do swojego czatu, handler po stronie serwera publikuje wiadomość do Redis ''newmessage' temat.
    4. gdy wiadomość zostanie opublikowana, Redis natychmiast powiadomi wszystkich oczekujących na obsługę, którzy wcześniej subskrybowali ten kanał.
    5. po powiadomieniu kod PHP, który utrzymuje otwarte zapytanie long-poll, może zwrócić żądanie z nową wiadomością czatu, więc wszyscy użytkownicy zostaną powiadomieni. Mogą w tym momencie odczytywać nowe wiadomości z bazy danych lub mogą być one przesyłane bezpośrednio do ładunku komunikatów.

Mam nadzieję, że moja ilustracja będzie łatwa do zrozumieć, jednak kolejki wiadomości jest bardzo szeroki temat, więc odnoszą się do zasobów wymienionych powyżej do dalszej lektury.

 25
Author: coffeesnake,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-12 15:33:27

Jak sprawdzić wyniki podczas połączenia Ajax jest nadal aktywny? Jestem świadomy funkcji sukcesu jQuery dla połączeń ajax, ale jak sprawdzić dane, gdy połączenie jest nadal w toku?

Właściwie to możesz. Podałem poprawioną odpowiedź na powyższe pytanie, ale nie wiem, czy jest ona nadal w toku, czy została zignorowana. Zapewnienie tutaj aktualizacji, aby dostępne były poprawne informacje.

Jeśli utrzymasz połączenie między Klientem a serwer otwarty możliwe jest wypychanie aktualizacji, przez które są dołączane do odpowiedzi. Ponieważ każda aktualizacja jest wywoływana w zdarzeniu XMLHttpRequest.onreadystatechange, a wartość {[2] } będzie równa 3. Oznacza to, że XMLHttpRequest.responseText nadal rośnie.

Możesz zobaczyć przykład tego tutaj: http://www.leggetter.co.uk/stackoverflow/7213549/

Aby zobaczyć kod JS wystarczy wyświetlić źródło. Kod PHP to:

<?php
$updates = $_GET['updates'];
if(!$updates) {
  $updates = 100;
}

header('Content-type: text/plain');
echo str_pad('PADDING', 2048, '|PADDING'); // initial buffer required

$sleep_time = 1;
$count = 0;
$update_suffix = 'Just keep streaming, streaming, streaming. Just keep streaming.';
while($count < 100) {
  $message = $count . ' >> ' . $update_suffix;
  echo($message);
  flush();
  $count = $count + 1;
  sleep($sleep_time);
}
?>

W przeglądarkach opartych na Gecko takich jak Firefox można całkowicie zastępuje responseText za pomocą multipart/x-mixed-replace. Nie podałem tego przykładu.

Nie wygląda na to, aby możliwe było osiągnięcie tego samego rodzaju funkcjonalności za pomocą jQuery.ajax. Wywołanie zwrotne success nie uruchamia się po wywołaniu zdarzenia onreadystatechange. Jest to zaskakujące, ponieważ dokumentacja stwierdza:

Nie jest dostępny mechanizm onreadystatechange, ponieważ success, error, complete i statusCode pokrywają wszystkie możliwe wymagania.

Więc dokumentacja jest potencjalnie błędna, chyba że źle ją interpretuję?

Możesz zobaczyć przykład, który próbuje użyć jQuery tutaj: http://www.leggetter.co.uk/stackoverflow/7213549/jquery.html

Jeśli spojrzysz na kartę Sieć w narzędziach programistycznych Firebug lub Chrome, zobaczysz Rozmiar pliku stream.php rosnący, ale wywołanie zwrotne success nadal nie jest fire.

 5
Author: leggetter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-08 16:40:44