2013-06-22 17 views
13

Ten problem dotyczy w szczególności Nodejitsu, ale podobne efekty wydają się występować w innych systemach VPS. Mam grę działającą w czasie rzeczywistym przy użyciu socket.io, a jedną rzecz, którą zauważyłem, jest to, że serwer od czasu do czasu czeka zbyt długo. Jeśli w tym okresie zostanie wysłanych wiele żądań, zachowują się tak, jakby wszystkie zostały umieszczone w kolejce i przetworzone jednocześnie. Podejrzewam, że jest niejasno skorelowany z obecnością innych użytkowników na udostępnianym sprzęcie (jak w przypadku każdego VPS).Wysoka latencja z NodeJS

W każdym razie, aby przetestować ten się (i upewnij się, że nie było ze względu na kod Mój gry), zbudowałem minimalny przypadek testowy:

express = require('express') 
http = require('http') 

app = express() 
server = http.Server(app) 

io = require('socket.io').listen(server) 

io.sockets.on('connection', function(sock){ 
    sock.on('perf', function(data, cb){ 
     cb([Date.now()]); //respond with the current time 
    }) 
}) 

app.get('/', function(req, res){ 
    res.header("Access-Control-Allow-Origin", "*") 
    res.header("Access-Control-Allow-Methods", "HEAD,GET,PUT,POST,DELETE") 
    res.header("Access-Control-Allow-Headers", "X-Requested-With") 

    res.end(JSON.stringify([Date.now().toString()])); //http equivalent of perf function 
}) 

server.listen(process.env.PORT || 6655, function(){ 
    console.log('listening now') 
}) 

miałem prostą pustą stronę HTML z gniazdka. io, które okresowo wysyłają zdarzenie i czas, o czasie, który trwało do wywołania zwrotnego. I nadal pokazuje to samo:

graph showing lag spike

pamiętać, że długość pręta reprezentuje pierwiastek kwadratowy z ilości czasu, nie ilość liniowy.

Kiedy zamiast polegać na socket.io, używam XHR do podobnego pomiaru bieżącego czasu odpowiedzi, wynik jest bardzo podobny, wiele odpowiedzi o małym opóźnieniu (choć z wyższą linią bazową niż websockets, zgodnie z oczekiwaniami) i sporadyczne skoki, które wydają się zbierać.

Dziwne jest to, że jeśli otworzysz go w wielu oknach przeglądarki i różnych przeglądarkach, wydaje się, że istnieje korelacja między różnymi przeglądarkami (i faktem, że jest ona całkowicie nieobecna lub znacznie rzadziej na niektórych serwerach), co wydaje się być sugerować, że jest to zjawisko po stronie serwera. Jednak w niektórych przeglądarkach występują opóźnienia, ale nie inne, a dwa okna Chrome z tej samej sesji wydają się być dokładnie dokładnymi duplikatami, co sugeruje, że dzieje się to lokalnie (na komputer lub przeglądarkę, sieć) mądry).

Od lewej do prawej: Incognito Chrome, Chrome (regularny), Firefox, Chrome (regularny)

charts on four windows

Zresztą zostało to mylące mnie przez kilka miesięcy i naprawdę chciałbym, aby zrozumieć, co powoduje to i naprawia.

+1

Jestem ciekawy, czy można otworzyć lokalne połączenie bezpośrednio na serwerze (być może z czymś podobnym do phantomjs) i wykonać te same pomiary, jeśli zobaczysz podobne skoki lub nie. Ciekawi mnie też, z jakiej wersji przeglądarek korzystasz i czy wracają one do flashowania, długiego sondowania czy iframe. Wygląda na to, że używasz ekspresu bez sesji, więc nie wydaje się, że jest to sesja związana z GC lub coś podobnego, i masz pewność, że serwer nie uruchamia się ponownie lub coś podobnego (co najprawdopodobniej oznacza wzrost cen wszystkich przeglądarek na poziomie w tym samym czasie, więc prawdopodobnie nie, ale po prostu zapytać). – hoonto

+0

Zgaduję, że już monitorowałeś statystyki serwera również podczas tych? Ciekawe, czy w tym samym czasie występują jakiekolwiek skorelowane skoki lub spadki pamięci lub procesora. Jeśli miałbyś dostęp do centrum danych, mógłbyś podłączyć się do lokalnego przełącznika i wyeliminować większość zakłóceń sieciowych, ale to prawdopodobnie nie jest opcja ... byłoby miło, gdyby oferowały usługę monitorowania socket.io z wnętrza danych Centrum. – hoonto

+1

W rzeczywistości można napisać lokalnego klienta węzła socket.io i uruchomić go lokalnie na tym samym serwerze, a także zmierzyć. Przepraszam, że tak bardzo cię spamuję, problemy z wydajnością mogą być jak igły w stogu siana, więc po prostu próbując wyrzucić wszystko, co tylko mogę o tym myśleć, może pomóc zawęzić problem do określonego obszaru. – hoonto

Odpowiedz

0

Wiem, że to może brzmieć dziwnie, ale mają rozważyć to nie jest problem z węzłem ale z ustawieniem OS. Czy sprawdziłeś uchwyty plików i liczbę połączeń, które system operacyjny pokazuje do gniazda? Czy masz również pewność, że limit czasu gniazda w systemie operacyjnym jest wystarczająco niski? Wystąpiły podobne problemy z wydajnością dźwięku z innym kodem i okazało się, że to system operacyjny, a nie kod. Sprawdź także pakiet i zobacz, co ma dla otwartych dozwolonych połączeń w gnieździe. Nie spojrzałem na kod węzła, ale napotkałem podobny problem z biblioteką klienta http w java. Aplikacja właśnie się zarchiwizowała i była to tylko kwestia konfiguracji z liczbą połączeń.

1

Zakładam, że sprawdzane, jeśli masz procesor lub ram problem.

Jedyną rzeczą, która może spowolnić węzeł w "zaskakujący" sposób, jest garbage collector - spróbuj uruchomić swój węzeł za pomocą --trace*, aby zobaczyć, co się dzieje. (Zobacz node --v8-options.)

Osobiście jestem przekonany, że niczego nie odkrywasz, ponieważ - i to tylko moje odczucie - problem jest gdzie indziej.

Dzięki temu doskonałemu opóźnieniu wynoszącemu wielokrotnie 500ms zakładam, że masz utratę pakietów. Możesz sprawdzić pod numerem ifconfig, czy jest to problem ogólny, a następnie tcpdump pakietów i sprawdzić, czy retransmitują.

+0

Podczas gdy zrobiłem tylko trochę z węzłem, napisałem sporo kodu serwera Java. Jedną z głównych rzeczy, o którą martwiliśmy się z opóźnieniem, było zbieranie śmieci. Problem z wieloma językami opartymi na VM (takimi jak Javascript/węzeł) polega na tym, że opóźnienie jest tak samo przewidywalne, jak pozwala na to VM. W przypadku Javy często pracowaliśmy ciężko, aby zminimalizować pobieranie śmieci, nie z powodu opóźnień, ale z powodu skoków opóźnień. Na wszelki wypadek przyjrzę się GC. – sasbury

0

Powodem, dla którego to widzisz jest Algorytm Walkera. Jest to algorytm używany na I/O, który buforuje dane przez pewien czas, a następnie wysyła większe porcje danych. Służy do zapisywania transmisji (w gniazdach). Możesz przeczytać więcej na ten temat tutaj http://en.wikipedia.org/wiki/Nagle's_algorithm

Aby wyłączyć algorytm Walkera (dobrze, gdy chcesz wysłać wiele małych żądań tak szybko, jak to możliwe) możesz zrobić socket.setNoDelay (true); jeśli używasz net.Socket(). W przypadku socket.io uważam, że Nagle jest już domyślnie wyłączony dla Websockets, ale niekoniecznie dla innych protokołów. Poleciłbym uruchomić test z net.Sockets z node.js, wyłączyć Nagle i zobaczyć, co otrzymasz.

+3

Nagle działa tylko dla jednego połączenia i łączy małe pakiety z dużymi. Nie może to być tutaj problemem, ponieważ masz nowe połączenie dla każdego połączenia. Nagle może stać się problemem tylko wtedy, gdy masz streaming w czasie rzeczywistym. – CFrei