Effizienz von while (true) ServerSocket Listen

8

Ich frage mich, ob eine typische while(true) ServerSocket-Abhörschleife einen ganzen Kern braucht, um zu warten und eine Clientverbindung zu akzeptieren (selbst wenn man runnable implementiert und Thread .start() verwendet)

Ich implementiere eine Art verteilter Computercluster und jeder Computer benötigt jeden Kern, den er zur Berechnung hat. Ein Master-Knoten muss mit diesen Computern kommunizieren (wobei statische Methoden aufgerufen werden, die die Funktionsweise des Algorithmus ändern).

Der Grund, warum ich Sockets verwenden muss, liegt an den plattformübergreifenden / sprachübergreifenden Fähigkeiten. In einigen Fällen wird PHP diese statischen Java-Methoden aufrufen.

Ich habe einen Java-Profiler (YourKit) benutzt und kann meinen laufenden ServerSocket-Listen-Thread sehen, der niemals schläft und immer läuft. Gibt es einen besseren Ansatz, um das zu tun, was ich will? Oder wird der Performance-Hit vernachlässigbar sein?

Bitte zögern Sie nicht, einen Vorschlag zu machen, wenn Sie sich einen besseren Weg vorstellen können (Ich habe RMI ausprobiert, aber es wird nicht in mehreren Sprachen unterstützt.

Danke allen

    
Submerged 17.05.2010, 20:39
quelle

4 Antworten

8

Wenn Sie so etwas meinen:

%Vor%

Dann, nein, der Aufruf von accept() "nimmt keinen ganzen Kern". Es ist ein blockierender Aufruf, der es ermöglicht, die CPU für einen anderen Thread zu terminieren, bis ein Client tatsächlich eine Verbindung herstellt. Sobald der Aufruf von accept() zurückkehrt, wird der aktuelle Thread für die Ausführung geplant und verbraucht CPU, bis er in der nächsten Iteration der Schleife auf accept() blockiert.

Um zu verhindern, dass der Listenrückstau anderer Clients zu groß wird, behandelt ein anderer Thread normalerweise die Interaktion mit dem neu akzeptierten Socket , sodass ein Thread sich auf das Akzeptieren neuer Clients konzentriert. Der Socket-Handlingthread kann mit NIO viele Sockets verarbeiten, oder er kann für einen einzelnen Socket bestimmt sein, der viel einfacher zu programmieren ist, aber nicht über viele hundert gleichzeitige Verbindungen skalieren kann.

    
erickson 17.05.2010, 21:11
quelle
5

Vielleicht möchten Sie sich die Java 1.4 nio-Bibliotheken und insbesondere ServerSocketChannel ansehen. Ich benutze dies sehr erfolgreich, um einen effizienten Server zu implementieren, die wichtigsten Bits des Codes sind:

%Vor%

Und der Listener ist nur eine Schleife, die läuft:

%Vor%     
mikera 17.05.2010 21:14
quelle
3
  

Ich habe einen Java-Profiler (YourKit) benutzt und ich kann meinen laufenden ServerSocket-Abhör-Thread sehen und er schläft nie und läuft immer.

Grundsätzlich führt der Profiler Sie in die Irre.

Ich gehe davon aus, dass Ihr Code so aussieht:

%Vor%

Dies wird keine wesentliche CPU verbrauchen ... es sei denn, Sie haben etwas pathologisches getan, wie den Aufruf von ServerSocket.setSoTimeout(int) mit einem kleinen Timeout.

    
Stephen C 18.05.2010 00:44
quelle
0

Lass den Kern ein wenig schlafen. Fügen Sie in Ihrer Runnable-Methode etwas wie

hinzu %Vor%

in jeder Schleife.

Das sollte die CPU-Auslastung erheblich reduzieren

Edit: schlechte Idee, siehe Kommentare, sorry, meine Schuld

Und: verwende nicht während (wahr). Es ist ein schreckliches Design, wie die Semantik nahelegt, dass das Wahre irgendwann nicht mehr wahr sein wird. Normalerweise möchten Sie eine flüchtige oder atomare Variable aus dem Hauptthread abfragen

%Vor%

Auf diese Weise hat der Haupt-Thread die Möglichkeit, den Listener-Thread zu stoppen.

    
Sean Patrick Floyd 17.05.2010 21:01
quelle