![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 2 707 Pomógł: 290 Dołączył: 16.12.2008 Skąd: Śląsk Ostrzeżenie: (0%) ![]() ![]() |
Powoli zaczynam zapoznawać się z tą technologią bo dużymi krokami zbliża się do mnie konieczność zbudowania komunikatora/czatu o dużej przepustowości.
Zastanawia mnie jednak jedno. Jak już dobrze zrozumiałem to ta technologia polega na tym, że przeglądarka wysyła żądanie pod podaną stronę (php) i oczekuje na odpowiedź. Wszystko jest tu dla mnie jasne, zamiast co 3 sekund wysyłać Request HTTP to wysyła go raz i czeka na odpowiedź. Ale zastanawia mnie co ma się dziać w tym momencie w skrypcie PHP, który np. odpytuje o nowe wiadomości? Czy tutaj będzie pętla, która co sekundę (sleep) odpytuje bazę o nowe wiadomości? Jeśli tak to gdzie tu korzyść oprócz zmniejszonej liczby Requestów, które chyba nie są takim obciążaniem jak odpytywanie bazy danych co X sekund? Ten post edytował markonix 8.10.2012, 20:13:44 |
|
|
![]() |
![]()
Post
#2
|
|
Grupa: Zarejestrowani Postów: 1 890 Pomógł: 339 Dołączył: 14.12.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
Po czym wnosisz, że 3 zapytania do bazy danych są bardziej kosztowne niż request HTTP? Już pomijając, że request robiłbyś co 3 sekundy, a zapytania do bazy co sekundę, więc opóźnienia byłyby 3 razy mniejsze.
Po pierwsze, jeśli używasz serwera Apache, to na każdy request HTTP odpala on oddzielny proces - jest to dosyć kosztowna operacja. Po drugie, każdy request składa się z nagłówków zapytania i odpowiedzi - zużywasz niepotrzebnie przepustowość. Wykonanie zapytania MySQL po kolumnach z indeksami przy raz otwartym połączeniu (zwłaszcza jeśli serwer aplikacji i bazy danych to ta sama maszyna) trwa, w zależności od ilości danych, relatywnie krótko. Poza tym zawsze możesz zapisywać wiadomości do bazy danych (jako archiwum), a bieżące wyświetlanie realizować na podstawie memcache. Ten post edytował sowiq 8.10.2012, 22:06:55 |
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 2 707 Pomógł: 290 Dołączył: 16.12.2008 Skąd: Śląsk Ostrzeżenie: (0%) ![]() ![]() |
Wnoszę to po tym, że po prostu baza jest zwykle wąskim gardłem i trzeba tak robić aby zapytań było jak najmniej.
Po to w końcu się cacheuje zapytania, a wcześniej je optymalizuje. Samo zapytanie np. przy czacie faktycznie nie jest kosztowne, bardziej chodzi o ilość. Czyli odpowiedzią na moje pytanie jest, że ta technologia nie służy zmniejszeniu liczby zapytań a jedynie REQUESTów. Z tej technologii korzysta FB i jakoś to działa, ale nie chce mi się aż wierzyć, że co sekundę jak nie częściej podczas rozmowy serwery odpytują bazę. Nadal jednak to nie jest prawdziwy real-time - opóźnienie opiera się na sleep chyba, że go nie użyjemy ale jeżeli zapytanie damy bez ograniczeń w pętle to nie uwierzę, że to nie zabije serwera (IMG:style_emoticons/default/smile.gif) |
|
|
![]()
Post
#4
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
PHP jest tu po prostu złą technologią. Zdecydowanie lepiej jest mieć dostęp do całego serwera aplikacji (patrz: Java, C#), gdzie w momencie napisania wiadomości przez jednego klienta (zapytanie INSERT do bazy danych) jesteś wstanie poinformować wszystkie inne wątki (obsługujące inne żądania HTTP/WebSocket) o pojawieniu się nowej wiadomości. Wtedy też wątki te mogą pobrać z bazy danych odpowiednie dane (zapytanie SELECT), bądź w ogóle pomijając bazę danych odczytać wiadomość przekazaną wraz z komunikatem o jej pojawieniu się (w takim przypadku baza danych służy wyłącznie za archiwum konwersacji).
@sowiq: Apache przy nowym żądaniu tworzy nowy wątek do jego obsługi, nie cały proces. |
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 915 Pomógł: 210 Dołączył: 8.09.2009 Skąd: Tomaszów Lubelski/Wrocław Ostrzeżenie: (0%) ![]() ![]() |
@Crozin dobrze prawi. To nie baza danych ma być "spoiwem" pomiędzy wymianą danych między klientami, ale sama aplikacja serwerowa.
Do aplikacji typu czat lepiej chyba użyć XMPP (np. ejabberd/openfire, po stronie klienta: strophejs), cometd czy nawet ape-project. Myśląc o budowie takiej aplikacji pomyśl też nad "wielozakładkowością". Czy lepiej, żeby dla każdej instancji strony (zakładki/nowego okna) w obrębie przeglądarki było nawiązywane osobne połączenie do serwera, czy może lepiej jak będzie jedno połączenie w obrębie wszystkich instancji, a synchronizacja czatu na wszystkich instancjach (zakładkach) będzie się odbywać np. za pomocą magazynu lokalnego. W przypadku jednego połączenia w obrębie przeglądarki dochodzi jeszcze problem "przerzucania roli" gdy mamy minimum 2 instancje strony i użytkownik zamyka tą z obsługą połączenia. Można też pójść na łatwiznę i ograniczyć działanie aplikacji tylko do jednej "zakładki", tak jak miała/ma nk (IMG:style_emoticons/default/smile.gif) PS. I fb i nk działał/działa na bazie protokołu XMPP (FB na zmodyfikowanym ejabberd). Jednak sprawdzane to było grubo ponad 1,5 roku temu. Ten post edytował redeemer 9.10.2012, 10:12:30 |
|
|
![]()
Post
#6
|
|
Grupa: Zarejestrowani Postów: 2 707 Pomógł: 290 Dołączył: 16.12.2008 Skąd: Śląsk Ostrzeżenie: (0%) ![]() ![]() |
Wszystkie te technologie, które wymieniłeś wymagają instalacji serwera na serwerze (oprogramowania) stąd to jest główne ograniczenie dla ich stosowania.
Tu już nie chodzi o to, że człowiekowi nie chce się włączyć puttiego ale o przenośność aplikacji. To tylko się zda gdy tworzymy coś naprawdę dużego i dedykowanego' albo dla siebie. Ale nawet jak dla siebie to gdy przenosimy hosting to musimy pamiętać o instalacji bo wszystko się sypnie (IMG:style_emoticons/default/smile.gif) Apre-project znam, trafiałem na tę stronę już kilka razy. Widzę jest to silnik typu "push". Ogólnie rozjaśniło mi się już rozróżnienie push/pull. Strona projektu nie wiedzieć czemu nie działa - tzn wiem, że na startowej były takie ruszające się małpiszony i chyba czat, a teraz mam "Your APE is coming...". Jeszcze myślę nad magazynem lokalnym. Faktycznie w tym momencie mam pełno ajaxowych zapytań w tradycyjnej formie (ani pull, ani push (IMG:style_emoticons/default/smile.gif) ), które np. odpytują o jakąś tam wartość liczbową - gdy się zmieni jest dźwięk. Niestety nigdy nie myślałem o tym, co powinno się dziać gdy otwarte są dwie czy więcej zakładek bo teraz dźwięk pojawi się X razy z różnym opóźnieniem i zastanawiam się czy właśnie nie wykorzystać tu localStorage? Bo ten ficzer miałeś na myśli? Ten post edytował markonix 9.10.2012, 11:24:16 |
|
|
![]()
Post
#7
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
@markonix: Obecnie ceny VPS-ów są na tyle niskie, że spokojnie można z nich korzystać przy średnich czy nawet małych stronach/aplikacjach.
|
|
|
![]()
Post
#8
|
|
Grupa: Moderatorzy Postów: 15 467 Pomógł: 1451 Dołączył: 25.04.2005 Skąd: Szczebrzeszyn/Rzeszów ![]() |
Cytat Po pierwsze, jeśli używasz serwera Apache, to na każdy request HTTP odpala on oddzielny proces - jest to dosyć kosztowna operacja. Po drugie, każdy request składa się z nagłówków zapytania i odpowiedzi - zużywasz niepotrzebnie przepustowość. Cytat @sowiq: Apache przy nowym żądaniu tworzy nowy wątek do jego obsługi, nie cały proces. Zależy, w jakim trybie jest skonfigurowany. Jest też opcja wątkowania. Cytat PS. I fb i nk działał/działa na bazie protokołu XMPP (FB na zmodyfikowanym ejabberd). Jednak sprawdzane to było grubo ponad 1,5 roku temu. Na NK też jest oparte o ejabberd. Rok szukali programistów do erlanga. (IMG:style_emoticons/default/tongue.gif) Cytat Niestety nigdy nie myślałem o tym, co powinno się dziać gdy otwarte są dwie czy więcej zakładek bo teraz dźwięk pojawi się X razy z różnym opóźnieniem i zastanawiam się czy właśnie nie wykorzystać tu localStorage? Bo ten ficzer miałeś na myśli? Prędzej sessionStorage. |
|
|
![]()
Post
#9
|
|
Grupa: Zarejestrowani Postów: 2 707 Pomógł: 290 Dołączył: 16.12.2008 Skąd: Śląsk Ostrzeżenie: (0%) ![]() ![]() |
@markonix: Obecnie ceny VPS-ów są na tyle niskie, że spokojnie można z nich korzystać przy średnich czy nawet małych stronach/aplikacjach. Odnosisz się do tej przenośności? Oj skrypt z koniecznością instalowania na serwerze oprogramowania nie sprzedałby się na Allegro. Na moje oko to 90% stron postawionych jest na hostingach (w tym darmowych) (IMG:style_emoticons/default/wink.gif) Ale to akurat tak tylko na marginesie skomentowałem. Wiadomo, coś za COŚ. @redeemer powiem Ci, że niezłą zagadkę zrobiłeś z tym przenoszeniem "serwera" pomiędzy zakładkami. Jedyne co mi przychodzi na myśl to brak odpowiedzi z zakładki serwerowej przez X czasu to sygnał dla zakładki drugiej, aby ta przejęła role serwera. |
|
|
![]()
Post
#10
|
|
Grupa: Zarejestrowani Postów: 1 890 Pomógł: 339 Dołączył: 14.12.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
@markonix, teraz mi się przypomniała pewna przygoda firmy, w której pracowałem. Mieliśmy zrobić chata dla sporego sajtu (kilka mln odsłon dziennie). Pierwszy pomysł to jabber, ale z braku entuzjazmu stanęło na deamonie w PHP i socketach, wtedy jeszcze używanych przez komunikację JavaScript <--> Flash <--> serwer. Wszystko działało bardzo ładnie aż do czasu jak wzrósł ruch. PHP zaczął gdzieś gubić pamięć. Powstał więc drugi deamon, który nadzorował proces PHP i co jakiś czas go restartował. Więc po stronie przeglądarki musiała powstać funkcja nadzorująca połączenie, która w razie potrzeby je ponawiała. I podobnych rzeczy pojawiało się coraz więcej. A finalnie, z tego co pamiętam, i tak zakończyło się na jakimś jabberze.
Więc przemyśl dokładnie, czy chcesz sobie dodawać roboty pchając się od początku w PHP. |
|
|
![]()
Post
#11
|
|
Grupa: Moderatorzy Postów: 15 467 Pomógł: 1451 Dołączył: 25.04.2005 Skąd: Szczebrzeszyn/Rzeszów ![]() |
Cytat Oj skrypt z koniecznością instalowania na serwerze oprogramowania nie sprzedałby się na Allegro. Na moje oko to 90% stron postawionych jest na hostingach (w tym darmowych) Ale to akurat tak tylko na marginesie skomentowałem. Wiadomo, coś za COŚ. Bo nie sprzedaje się skryptów, tylko dostęp do nich. (IMG:style_emoticons/default/tongue.gif) Model SaaS ma się dobrze i klienci są mniej upierdliwi, bo za całą infrastrukturę programową odpowiadasz Ty. [; Z doświadczenia - stawianie demonów w PHP jest bez sensu. Nie mam pojęcia, z jakiego powodu, po jakimś czasie albo się wysypie, albo w ogóle nie wystartuje na innej maszynie, choć konfiguracja jest bliźniacza. Python takich problemów nie ma, czego już totalnie nie rozumiem... O.o' A ejabberd + klient Jabbera, to chyba najlepsze, co można w tej chwili zrobić nie pisząc od zera i śpiąc spokojnie, jeśli chodzi o obciążenie. Erlang, to potężny język, zwłaszcza jeśli chodzi o skalowalność. [; |
|
|
![]()
Post
#12
|
|
Grupa: Zarejestrowani Postów: 915 Pomógł: 210 Dołączył: 8.09.2009 Skąd: Tomaszów Lubelski/Wrocław Ostrzeżenie: (0%) ![]() ![]() |
@redeemer powiem Ci, że niezłą zagadkę zrobiłeś z tym przenoszeniem "serwera" pomiędzy zakładkami. Jedyne co mi przychodzi na myśl to brak odpowiedzi z zakładki serwerowej przez X czasu to sygnał dla zakładki drugiej, aby ta przejęła role serwera. Long polling ma to do siebie, że połączenie może wisieć nawet przez 30 sekund. Lepszym rozwiązaniem będzie dodatkowa funkcja wywoływana z pewnym interwałem czasowym, która co parę sekund będzie odświeżała jakąś zmienną typu timestamp w magazynie lokalnym w "głównej" instancji. Inne instancje będą monitorować wartość tej zmiennej i jeżeli jakiś warunek nie będzie spełniony przejmą jego rolę. Tu z kolei pojawia się problem konkurencyjności, bo js nie jest językiem wielowątkowym i nie możemy określić sekcji krytycznej (brak mutexów), w związku z czym teoretycznie podczas zamknięcia głównej instancji jej role może przejąć w tym czasie wiele innych zakładek, które działały wcześniej w tzw. trybie mirror. Zwykle w serwerach XMPP można włączyć opcję (lub ją sobie dopisać), aby "multisesje" nie były aktywne, w tym wypadku jeżeli wiele instancji tego samego klienta będzie podłączonych do serwera, wszystkie poza jedną dostaną od serwera stosowną wiadomość disconnect, która po obsłużeniu po stronie klienta spowoduje, aby instancja przeszła w tryb "mirror", czyli bez połączenia do serwera. Nam jakiś czas temu udało się zbudować taką aplikację zintegrowaną z serwisem społecznościowym, gdzie dodatkowo są też reguły, dotyczące komu kto może wysyłać wiadomości. Użyliśmy ejabberd (na początku był to openfire), strophejs (z modyfikacjami), oraz http://www.jstorage.info/. Niestety branch nigdy nie został włączony do gałęzi production, a szkoda. Jako lekturę mogę polecić, co prawda już nie pierwszej świeżości (2010 rok), ksiażkę autora biblioteki strophejs Professional XMPP Programming with JavaScript and jQuery |
|
|
![]()
Post
#13
|
|
Grupa: Zarejestrowani Postów: 2 707 Pomógł: 290 Dołączył: 16.12.2008 Skąd: Śląsk Ostrzeżenie: (0%) ![]() ![]() |
Jeszcze wracając do "prostego" polling.
Jaki czas powinno mieć oczekiwanie na odpowiedź? Początkowo wydawało mi się czym dłużej tym lepiej bo w końcu chodzi o zmniejszenie liczby requestów. No ale gdy stworzyłem testowy skrypt to po 45 sekundach otrzymałem error 500. No i teraz pytanie co z tym zrobić? - Przechwycić błąd
i od nowa oczekiwanie? - Starać się jak najbardziej zwiększyć czas wykonywania skryptu (albo najlepiej no-limit)? Te pierwsze wydaje mi się bardziej bezpiecznie ale przykładowo przymierzam się do poprawek w obecnych skryptach gdzie np. teraz wartości odświeżane są co 15 sekund. Wprowadzając omawianą technikę to będzie oszczędność dość mizerna (1 zamiast 3), a gdyby execute_time wynosił np. 10 minut to już gdzieś oszczędność na poziomie 40 requestów i jakoś bardziej działa to na wyobraźnie i motywuje do przeróbek w obecnych skryptach. Ten post edytował markonix 10.10.2012, 11:58:32 |
|
|
![]()
Post
#14
|
|
Grupa: Zarejestrowani Postów: 915 Pomógł: 210 Dołączył: 8.09.2009 Skąd: Tomaszów Lubelski/Wrocław Ostrzeżenie: (0%) ![]() ![]() |
http://tools.ietf.org/html/rfc6202#page-15 5.5 Timeouts (ale cały dokument jest warty uwagi)
Co ciekawe w drafcie http://tools.ietf.org/html/draft-loreto-ht...onal-07#page-15 jest to bardziej rozwinięte i możemy tam przeczytać dodatkowo: Cytat Several experiments have shown success with timeouts as high as 120 seconds, but generally 30 seconds is a safer value. Therefore vendors of network equipment wishing to be compatible with the HTTP long polling mechanism are advised to implement a timeout |
|
|
![]()
Post
#15
|
|
Grupa: Zarejestrowani Postów: 2 707 Pomógł: 290 Dołączył: 16.12.2008 Skąd: Śląsk Ostrzeżenie: (0%) ![]() ![]() |
Znowu wracam do problemu z long polling.
Oki, mniej requestów, zapytania są optymalne, ale teraz naszła mnie kolejna myśl co do wydajności takiego rozwiązania, a mianowicie liczba połączeń z bazą. Przy pracy nad czatem zawiesiłem parę razy serwer - "too many connections". Oczywiście był to wynik błędnych pętli ale ten błąd kieruje uwagę na powyższy problem. Funkcje z rodziny sleep nie kończą w żaden sposób skryptu, tak więc przyjmując te 30 sekund jeden użytkownik przez 30 sekund zajmuje bazę, albo przynajmniej utrzymuje z nią połączenie. Czy dobrze myślę? Czy utrzymanie połączenia może spowodować jakieś problemy? Czy może przy każdym obrocie pętli zamykać połączenie i otwierać na nowo? Ten post edytował markonix 29.09.2013, 19:52:22 |
|
|
![]()
Post
#16
|
|
Grupa: Zarejestrowani Postów: 592 Pomógł: 62 Dołączył: 3.08.2006 Ostrzeżenie: (0%) ![]() ![]() |
Ciekawym rozwiązaniem jest Tornado. Jest to asynchroniczny framework napisany w Pythonie wprost stworzony do long polling.
W niedawno stworzonej aplikacji typu real-time nie korzystałem z żadnych sleepów... W skrócie był wątek producenta (lub wątki, bez znaczenia), który dodawał do kolejek nowe zdarzenia. W tym samym czasie żądania long-polling czekały na kolejce. Kiedy tylko coś pojawiło się w kolejce, to żądanie było wznawiane i odpowiedź szła do użytkownika. Może pomyśl w tym kierunku. Odnośnie pytania, to zastosuj pulę połączeń (patrz np. ADO.NET). PS. Także nie polecam PHP do tego typu aplikacji. Osobiście stawiam na Pythona, od biedy Javę (IMG:style_emoticons/default/smile.gif) |
|
|
![]() ![]() |
![]() |
Aktualny czas: 23.08.2025 - 17:56 |