Drosselt Mac OS X die Rate der Socket-Erstellung?

7

Dies mag programmierungsbezogen erscheinen, aber dies ist eine Frage des Betriebssystems.

Ich schreibe einen kleinen Hochleistungsdämon, der Tausende von Verbindungen pro Sekunde benötigt. Es funktioniert gut unter Linux (speziell Ubuntu 9.10 unter EC2). Wenn ich unter Mac OS X ein paar tausend Verbindungen (ungefähr 16350) in einen Benchmark werfe, der einfach eine Verbindung öffnet, es tut und die Verbindung schließt, bleibt das Benchmark-Programm einige Sekunden lang hängen und wartet darauf, dass ein Socket verfügbar wird bevor Sie fortfahren (oder eine Zeitüberschreitung im Prozess).

Ich habe sowohl Apache Bench als auch Siege verwendet (um sicherzustellen, dass es nicht die Benchmark-Anwendung ist).

Warum / wie begrenzt Mac OS X die RATE, mit der Sockets verwendet werden können, und kann ich dies verhindern?

Oder ist noch etwas los?

Ich weiß, dass es ein Dateideskriptor-Limit gibt, aber das treffe ich nicht. Es gibt keinen Fehler beim Akzeptieren eines Sockets, es bleibt einfach eine Weile nach dem ersten (ungefähr) 16000 hängen und wartet - ich nehme an - darauf, dass das Betriebssystem einen Socket freigibt. Dies sollte nicht passieren, da alle vorherigen Sockets zu diesem Zeitpunkt geschlossen sind. Sie sollen mit der Geschwindigkeit verfügbar sein, mit der sie geschlossen sind, und zwar unter Ubuntu, aber unter Mac OS X scheint es eine Art Verzögerung von mehreren (5-10?) Sekunden zu geben.

Ich habe versucht, mit ulimit in alle Richtungen zu optimieren. Nada.

pbhogan
quelle
Überqueren Sie nicht post - serverfault.com/questions/145907/…
MDMarra
Dies ist eine gute Frage, und es ist eine dieser Grauzonen, die bei Superuser- oder Serverfehlern gleichermaßen akzeptabel sein können . Trotzdem sollten Sie nicht zuerst einen Crosspost erstellen und später Fragen stellen. Post auf der einen oder anderen Seite. Wenn nach einer angemessenen Zeit keine guten Antworten eingehen, können Sie den Moderator darauf hinweisen, dass er auf die andere Site migriert werden soll.
Quacksalber Quijote
1
@ MarkM Warum nicht? Es gilt für beide und obwohl es für ServerFault etwas relevanter ist, habe ich die Antwort hier erhalten und die Antwort an die andere gesendet. Es ist sogar für StackOverflow relevant, obwohl ich mich entschieden habe, dort nicht zu posten, da ich mir ziemlich sicher war, dass das Problem nicht im Code enthalten war. Cross-Posting ist nicht schlecht, wenn es für jede Community relevant ist, da es für beide einen Wert bietet. Sie wissen nicht immer, aus welchem ​​Winkel die Antwort kommt.
pbhogan
@quack quixote Mir war nicht bewusst, dass es dafür ein Protokoll gibt. Ich bin damit nicht wirklich einverstanden, werde aber versuchen, es in Zukunft zu verfolgen.
Pbhogan
1
Im Allgemeinen sind Crossposts schlecht (da der Fragesteller nicht weiß, zu welcher Site eine Frage gehört; normalerweise sind das Ergebnis Fragenmigrationen und -duplikationen). Das ist hier nicht der Fall - wie gesagt, ich denke, dass dies auf beiden Seiten gleichermaßen akzeptabel ist. Trotzdem denke ich, dass Crossposts vermieden werden sollten. Post-on-One-Then-Migrate-falls-notwendig scheint mir ein vernünftiges Protokoll zu sein. Vielen Dank!
Quacksalber Quijote

Antworten:

16

Mac OS X beginnt bei 49152 mit dem Öffnen kurzlebiger Ports. Portnummern sind 16-Bit-Ganzzahlen ohne Vorzeichen, sodass 65535 Ports möglich sind. 65535 - 49152 = 16383. Ich glaube, Sie haben 16K-Ports in TIME_WAIT.

Update : Möglicherweise möchten Sie sich die folgenden sysctl (8) -Variablen ansehen:

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  

Ich denke, wenn Sie hifirst auf einen niedrigeren Wert einstellen, erhöhen Sie die Anzahl der kurzlebigen Ports, die auf Ihrem System verfügbar sind.

Möglicherweise gibt es eine Socket-Option oder etwas, das den Stack anweist, grundsätzlich gegen die TCP-Spezifikation zu verstoßen und einen nicht standardmäßigen Wert für TIME_WAIT zu verwenden, aber ich bin nicht genug von einem Mac OS X-Socket-Programmierer, um das zu wissen.

Update 2 : Sie möchten wahrscheinlich setsockopt (2) verwenden, um SO_REUSEADDR festzulegen.

Spiff
quelle
Du hast Recht. Netstat sagt mir, dass sie alle in TIME_WAIT sind. Ich verwende SO_REUSEADDR bereits auf dem Daemon, aber die Benchmark-Apps tun dies wahrscheinlich nicht, weshalb es umkippt. Natürlich ist es höchst unwahrscheinlich, dass ein einzelner Client ohnehin so viele gleichzeitige Verbindungen öffnet (im Gegensatz zur Wiederverwendung einer oder mehrerer Verbindungen).
pbhogan
sudo sysctl -w net.inet.ip.portrange.first = 32768 half, das Problem zu lindern. Unter Mac OS X muss wahrscheinlich sowohl die erste als auch die erste Einstellung festgelegt werden, da sie gleich behandelt werden und Sie nicht wissen, welche verwendet wird. Siehe auch: ncftp.com/ncftpd/doc/misc/ephemeral_ports.html#FreeBSD
pbhogan
Diese Antwort löste absolut ein ähnliches Problem, das ich mit Java / JMeter hatte, 1000 Anfragen / Sekunde an einen schnellen Webdienst (lokale Perfektionstests).
StaxMan