2012-02-06 9 views
5

Powiel możliwe:
'ab' program freezes after lots of requests, why?Dlaczego prosty serwer Thin przestaje odpowiadać przy 16500 zapytaniach podczas testów porównawczych?

Oto prosty serwer testowy:

require 'rubygems' 
require 'rack' 
require 'thin' 

class HelloWorld 

    def call(env) 
    [200, {"Content-Type" => "text/plain"}, "OK"] 
    end 
end 

Rack::Handler::Thin.run HelloWorld.new, :Port => 9294 
#I've tried with these added too, 'rack.multithread' => true, 'rack.multiprocess' => true 

Oto przebieg testu:

$ ab -n 20000 http://0.0.0.0:9294/sdf 
This is ApacheBench, Version 2.3 <$Revision: 655654 $> 
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 
Licensed to The Apache Software Foundation, http://www.apache.org/ 

Benchmarking 0.0.0.0 (be patient) 
Completed 2000 requests 
Completed 4000 requests 
Completed 6000 requests 
Completed 8000 requests 
Completed 10000 requests 
Completed 12000 requests 
Completed 14000 requests 
Completed 16000 requests 
apr_poll: The timeout specified has expired (70007) 
Total of 16347 requests completed 

Rozkłada się na około 16500. Dlaczego? Jak mogę się dowiedzieć, co się dzieje. Czy jest to GC w Ruby, czy jest to coś z wieloma dostępnymi gniazdami sieciowymi na maszynie OS X? Mam pamięć MPB 2,5 Ghz 6G.


Edit

Po krótkiej dyskusji tutaj i testowania różnych rzeczy, wydaje się, zmieniając net.inet.tcp.msl od 15000 do 1000ms sprawia problemu wysokiej częstotliwości testowania serwerów internetowych z ab odejść.

sudo sysctl -w net.inet.tcp.msl=1000 # this is only good for local development 

Zobacz pytanie z odpowiedzią na ten problem. 'ab' program freezes after lots of requests, why?

+1

Znalazłeś przyczynę ?? Potencjalnym wyjaśnieniem może być to, że system operacyjny zachowuje gniazdo w stanie "ostatnio używanym" i nie używa go ponownie przez kilka minut. Wygląda na to, że można zrekonfigurować warstwę IP systemu operacyjnego, aby tego nie robić. – radiospiel

+1

Jeśli to pomaga, mogę odtworzyć to dokładne zachowanie na moim MBP. 16359 zapytań zakończonych. Nie mam pojęcia, co to powoduje. –

+1

Hmm, myślę głośno, ta liczba jest podejrzanie bliska 16384 ... –

Odpowiedz

5

Dodam tutaj rozwiązanie dla jasności. Prawidłowym rozwiązaniem do przeprowadzania testów wysokiej częstotliwości z ab na os X jest zmiana ustawienia "net.inet.tcp.msl" z 15000ms na 1000ms. Powinno to zostać wykonane tylko w skrzynkach programistycznych.

sudo sysctl -w net.inet.tcp.msl=1000 # this is only good for local development 

Ta odpowiedź została znaleziona po dobra praca detektywa wykonywane w komentarzach i tutaj przychodzi z odpowiedzią na bardzo podobnym pytaniem oto odpowiedź: https://stackoverflow.com/a/6699135/155031

2

Myślę, że mam.

Gdy ab nawiązuje połączenia z serwerem testowym, otwiera port źródłowy (na przykład 50134) i nawiązuje połączenie z portem docelowym (9294).

Porty, które ab otwiera port źródłowy, są określane przez ustawienia sysctl: net.inet.ip.portrange.first i net.inet.ip.portrange.last. Na przykład, na moim komputerze:

philippotter ~ $ sysctl -a | grep ip.portrange 
net.inet.ip.portrange.lowfirst: 1023 
net.inet.ip.portrange.lowlast: 600 
net.inet.ip.portrange.first: 49152 
net.inet.ip.portrange.last: 65535 
net.inet.ip.portrange.hifirst: 49152 
net.inet.ip.portrange.hilast: 65535 

Oznacza to, że porty źródłowe AB będzie w przedziale od 49152 do 65535, co jest w sumie 16384.

HTTP jest protokołem TCP. Gdy połączenie TCP jest zamknięte, przechodzi ono do numeru TIME_WAIT state, podczas gdy czeka ono na to, aby pozostałe pakiety tranzytowe dotarły do ​​miejsc docelowych. Oznacza to, że port nie nadaje się do żadnego innego celu, dopóki nie zostanie osiągnięty limit czasu.

Łącząc to wszystko, ab szybko wykorzystuje wszystkie dostępne porty źródłowe; przejdą do stanu TIME_WAIT; nie można ich użyć ponownie; ab nie może utworzyć więcej połączeń.

Możesz to zobaczyć, jeśli zabijesz ab kiedy zawiesi się i uruchomisz go ponownie - nie będzie on w stanie stworzyć żadnych połączeń!

+1

Wygląda na to, że jesteśmy bliżej do problemu! Ale dlaczego dane wyjściowe 'netstat -p tcp' nie są wypełnione wartościami TIME_WAIS i dlaczego inne programy wciąż mogą otwierać połączenia? – sunkencity

+0

Uruchamiając nowy serwer i uruchamiając ab, wydaje się, że ostatnie żądanie zawiesza się na 'tcp4 0 0 localhost.52892 localhost.http SYN_SENT', a następnie po chwili żądanie kończy się. (Próbowałem uruchomić serwer na porcie 80 zamiast wyższego portu) – sunkencity

+0

@ sunkencity hmm, dobre pytania. Być może jednak nie jest to TIME_WAIT. –

Powiązane problemy