Beim Versuch, eine große Anzahl von TCP-Verbindungen parallel aufzubauen, beobachte ich ein seltsames Verhalten, das ich für einen potentiellen Fehler in gen_tcp
halte.GESCHLOSSENER Fehler beim parallelen Herstellen einer großen Anzahl von Verbindungen mit gen_tcp (Bug?)
Das Szenario ist ein Server, der auf einem Port mit mehreren gleichzeitigen Akzeptoren abhört. Von einem Client aus stelle ich eine Verbindung her, indem ich gen_tcp:connect/3
anrufe, danach sende ich eine "Ping" -Nachricht an den Server und warte im passiven Modus auf eine "Pong" -Antwort. Bei der sequenziellen Ausführung von 'get_tcp: connect/3' funktioniert alles gut, auch für eine große Anzahl von Verbindungen (ich habe bis zu ~ 28000 getestet).
Das Problem tritt auf, wenn versucht wird, viele Verbindungen parallel aufzubauen (abhängig von der Maschine zwischen ~ 75 und mehreren hundert). Während die meisten Verbindungen noch hergestellt werden, scheitern einige Verbindungen mit einem closed
Fehler in gen_tcp:recv/3
. Das Seltsame ist, dass diese Verbindungen nicht vorher versagten, die Aufrufe an gen_tcp:connect/3
und gen_tcp:send/2
waren beide erfolgreich (d. H. Zurückgegeben ok
). Auf der Serverseite sehe ich keine passende Verbindung für diese "seltsamen" Verbindungen, d. H. Keine Rückkehr gen_tcp:accept/1
. Es ist mein Verständnis, dass eine erfolgreiche 'get_tcp: connect/3' zu einer übereinstimmenden akzeptierten Verbindung auf der Serverseite führen sollte.
Ich habe bereits eine bug report eingereicht, dort finden Sie eine detailliertere Beschreibung und ein minimales Codebeispiel, um das Problem zu demonstrieren. Ich konnte das Problem unter Linux und Mac OS X und mit verschiedenen Erlang-Versionen reproduzieren.
Meine Frage lautet hier:
- Ist jemand in der Lage, das Problem zu reproduzieren und bestätigen kann, dass diese fehlerhaftes Verhalten ist?
- Irgendwelche Ideen für eine Problemumgehung? Wie geht man mit diesem Problem um, andere starten alle Verbindungen nacheinander (was ewig dauert)?
Ohne auf das Beispiel zu schauen, mein erster Gedanke ist, dass die tcp 'backlog' Größe möglicherweise zu klein ist. Hast du versucht es zu erhöhen? (http://erlang.org/doc/man/gen_tcp.html#listen2) Siehe http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux .html für eine Beschreibung dessen, was es tut. – johlo
Ich stimme @johlo zu. Ich habe Ihren Code untersucht und Sie verwenden nicht die Option "{backlog, B}". Mögliches Duplikat von [Erlang TCP Sockets wird geschlossen] (http://stackoverflow.com/questions/32511676/erlang-tcp-sockets-get-closed) –
@johlo Danke, toller Tipp und toller Link. Durch das Erhöhen des Backlogs wurde das Problem gelöst und der Artikel erklärt, warum der Aufruf von 'gen_tcp: connect/3' ohne Fehler zurückkehrt (weil er das SYN/ACK vom Server erhalten und das finale ACK gesendet hat), aber der Server nicht endet Status festgelegt (weil es die letzte ACK ignoriert hat). – jvf