2012-02-06 9 views
5

Eventuali duplicati:
'ab' program freezes after lots of requests, why?Perché un semplice server Thin smette di rispondere a 16500 richieste durante l'analisi comparativa?

Ecco un semplice server di prova:

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 

Ecco una corsa di prova:

$ 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 

Si rompe intorno al 16500. Perché? Come posso scoprire cosa sta succedendo. È GC in ruby ​​o è qualcosa con il numero di socket di rete disponibili su una macchina OS X. Ho una memoria MPB 2.5 Ghz 6G.


Modifica

Dopo qualche discussione qui e testando varie cose, sembra come cambiare net.inet.tcp.msl da 15000 a 1000 ms rende il problema di verificare server web ad alta frequenza con ab andare via.

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

Vedere la domanda di riferimento con la risposta a questo problema. 'ab' program freezes after lots of requests, why?

+1

Hai trovato la ragione ?? Una possibile spiegazione potrebbe essere che il sistema operativo mantiene un socket in uno stato "usato di recente" e non lo riutilizza per alcuni minuti. Apparentemente si può riconfigurare il livello IP del SO per non farlo. – radiospiel

+1

Se aiuta, posso riprodurre questo comportamento esatto sul mio MBP. 16359 richieste completate. Non ho idea di cosa lo causi. –

+1

Hmm, pensando ad alta voce, questo numero è sospettosamente vicino a 16384 ... –

risposta

5

Aggiungerò qui la soluzione per motivi di chiarezza. La soluzione corretta per la gestione dei test ad alta frequenza con ab on os X è quella di cambiare l'impostazione 'net.inet.tcp.msl' da 15000ms a 1000ms. Questo dovrebbe essere fatto solo su scatole di sviluppo.

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

Questa risposta è stata trovata dopo il buon lavoro investigativo eseguito nei commenti qui e proviene da una risposta ad una domanda molto simile ecco la risposta: https://stackoverflow.com/a/6699135/155031

2

Penso di averlo capito.

Quando ab crea connessioni al server di test, apre una porta di origine (ad esempio 50134) e stabilisce una connessione alla porta di destinazione (9294).

Le porte che ab si apre per la porta di origine sono determinate dalle impostazioni di sysctl net.inet.ip.portrange.first e net.inet.ip.portrange.last. Ad esempio, sulla mia macchina:

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 

Ciò significa che le porte origine di ab sarà nella gamma da 49152 e 65535 che complessivamente 16384.

HTTP è un protocollo TCP. Quando una connessione TCP viene chiusa, passa a TIME_WAIT state, mentre attende che i pacchetti in transito rimanenti raggiungano le loro destinazioni. Ciò significa che la porta non è utilizzabile per nessun altro scopo fino al raggiungimento del timeout.

Quindi, mettendo tutto questo insieme, ab usa molto rapidamente tutte le porte sorgente disponibili; entrano nello stato TIME_WAIT; non possono essere riutilizzati; ab non è in grado di creare altre connessioni.

È possibile vedere questo se si uccide ab quando si blocca, ed eseguirlo di nuovo - non sarà in grado di creare connessioni !

+1

Sembra che siamo più vicini al problema! Ma perché l'output di 'netstat -p tcp' non è pieno di TIME_WAITS e perché altri programmi possono ancora aprire connessioni? – sunkencity

+0

Avvio di un nuovo server ed esecuzione ab, sembra che l'ultima richiesta si blocca su 'tcp4 0 0 localhost.52892 localhost.http SYN_SENT' e quindi dopo un po 'la richiesta scade. (Ho provato a eseguire il server sulla porta 80 anziché su una porta superiore) – sunkencity

+0

@sunkencity hmm, buone domande. Forse dopotutto non è TIME_WAIT. –