2009-07-22 3 views
2

Ich habe eine Anwendung, in C++ geschrieben, die boost :: asio verwendet. Er wartet auf Anforderungen an einem Socket und führt für jede Anforderung eine CPU-gebundene Arbeit durch (z. B. keine Festplatte oder Netzwerk-E/A) und antwortet dann mit einer Antwort.Ich habe einen Server auf Sockets zuhören, was ist ein guter Ansatz, CPU-gebundene Anfragen mit mehreren Threads zu bedienen?

Diese Anwendung wird auf einem Multi-Core-System ausgeführt werden, so dass ich (mindestens) 1 Thread pro Kern planen, um Anfragen parallel zu verarbeiten.

Was ist der beste Ansatz hier? Dinge zu denken:

  • ich eine feste Größe Thread-Pool benötigen (zB 1 Thread pro CPU)
  • Werden mehr Anfragen kommen, als ich Threads haben, dann werden sie (vielleicht in die Warteschlange gestellt werden müssen ? o/s Sockets Layer)

Derzeit ist der Server Single-Threaded:

  • es ist für eine Client-Anfrage wartet
  • Sobald es eine erf erhält uest, führt es die Arbeit, und schreibt die Antwort zurück, dann für die nächste Anforderung beginnt warten

Update:

Genauer gesagt: was Mechanismus sollte ich das verwenden, um sicherzustellen, wenn der Server, dass eingehende besetzt ist Anfragen werden in die Warteschlange gestellt? Welchen Mechanismus sollte ich verwenden, um eingehende Anfragen auf die N Threads zu verteilen (1 pro Kern)?

+0

Es sieht so aus "HTTP Server 3" auf dieser Seite könnte ein guter Ansatz sein: http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/examples.html#boost_asio.examples. http_server_3 –

Antwort

2

Ich sehe nicht, dass es viel zu berücksichtigen gibt, dass Sie nicht bereits abgedeckt haben.

Wenn es wirklich CPU-gebunden ist, hilft das Hinzufügen von Threads über die Anzahl der Kerne nicht viel außer, wenn Sie eine Menge Anfragen haben werden. In diesem Fall kann die Listenwarteschlange Ihren Anforderungen entsprechen oder nicht, und es könnte besser sein, einige Threads zu haben, um die Verbindungen zu akzeptieren und sie selbst in eine Warteschlange zu stellen. Überprüfen Sie die Listen-Backlog-Werte für Ihr System und experimentieren Sie ein wenig mit der Anzahl der Threads.

UPDATE:

hören() einen zweiten Parameter, der Ihr Wunsch ist OS/TCP Warteschlangentiefe. Sie können es auf das OS-Limit einstellen. Darüber hinaus müssen Sie mit den Systemknöpfen spielen. Bei meinem derzeitigen System ist es 128, also ist es nicht riesig, aber auch nicht trivial. Überprüfen Sie Ihr System und überlegen Sie, ob Sie etwas Größeres als das Standardmodell benötigen.

Darüber hinaus gibt es mehrere Richtungen, die Sie gehen können. Betrachten Sie KISS - keine Komplexität, bevor es wirklich benötigt wird. Beginnen Sie mit etwas Einfachem wie nur einen Thread haben, um Verbindung zu akzeptieren (bis zu einem gewissen Limit) und plop sie in einer Warteschlange. Worker-Threads holen sie ab, verarbeiten sie, schreiben das Ergebnis und schließen den Socket.

Bei der aktuellen Geschwindigkeit der Boost-Updates meiner Distribution (und meinem fehlenden Willen, es selbst zu kompilieren) wird es 2012 sein, bevor ich mit ASIO spiele - damit kann ich nicht helfen.

+0

Es ist CPU-gebunden. Ich werde meine Frage mit weiteren Einzelheiten aktualisieren. –

+0

Es ist relativ einfach, auf Windows und Linux zu bauen. Ich bin neu in Linux, und sogar ich kann es tun :) –

+0

@Alex - Sie inspirierten mich. Der Prozess war nicht zufällig, aber nicht annähernd so schlimm wie beim letzten Mal. –

1

ACE http://www.cs.wustl.edu/~schmidt/ACE/book1/

Es hat alles, was man braucht. Thread Management und Warteschlangen und als zusätzlicher Bonus eine portable Art, Socket Server zu schreiben.

+0

Danke für den Vorschlag, aber ich werde im Moment nicht von Boost auf ACE wechseln. –

+0

@Alex - nicht sicher, ob Mamin vorschlug, ACE zu verwenden oder nur das Buch zu lesen. Das Buch ist stark auf ACE ausgerichtet, umfasst jedoch einige wichtige Muster, die unabhängig von der Bibliothek implementiert werden können. – Duck

+0

@Duck: Ah, thx, ich werde mir das Buch ansehen. –

1

Wenn Sie den überladenen Konstruktor von basic_socket_acceptor zum Binden und Abhören eines bestimmten Endpunkts verwenden, verwendet er SOMAXCONN als Rückstand von ausstehenden Verbindungen im Aufruf von listen(). Ich denke (nicht sehr sicher), dass dies in Windows auf 250 abbildet. Daher akzeptiert der Netzwerkdienstanbieter (im unbeaufsichtigten Modus) Clientverbindungen bis zu diesem Grenzwert und stellt sie in eine Warteschlange für die Verarbeitung durch Ihre Anwendung. Ihr nächster Annahmelauf ruft eine Verbindung aus dieser Warteschlange auf.

+0

Danke. Ich bin auf Linux, ist der Standard max dort ähnlich? –

+0

Die Seite http://linux.die.net/man/2/listen sagt, dass SOMAXCONN ist 128 in Linux 2.0 & 2.2 – Modicom

+0

In aktuellen Kernel "cat/proc/sys/net/core/somaxconn", um den aktuellen Wert zu erhalten . "echo 2000>/proc/sys/net/core/somaxconn" zu erhöhen. –

Verwandte Themen