Sonntag, April 5, 2020

Thread pro Verbindung vs-Reaktor-Muster (mit einem thread-pool)?

Möchte ich mal ein einfaches multiplayer-Spiel als Teil meiner C++ – learning-Projekt.

So, ich dachte, da bin ich bei ihm, ich möchte es tun richtig im Gegensatz zu nur immer-es-getan.

Wenn ich das richtig verstanden habe: Apache verwendet eine Thread-per-connection-Architektur, während nginx nutzt eine event-Schleife und dann widmet ein Arbeiter [x] für die eingehende Verbindung. Ich denke, nginx ist klüger, denn es unterstützt einen höheren Grad an Parallelität. Richtig?

Habe ich auch in diesem clevere Analogie, aber ich bin nicht sicher, ob es angewendet werden könnte, um meine situation. Die Analogie scheint auch sehr idealist. Ich habe selten gesehen, meine computer laufen auf 100% CPU (auch mit einer umptillion Chrome tabs öffnen, Photoshop und was-nicht gleichzeitig ausgeführt werden)

Außerdem, ich bin gekommen, über eine SO post (irgendwie verschwand es aus meiner Geschichte), wo ein user gefragt, wie viele threads verwendet werden soll, und eine der Antworten war, dass es vollkommen akzeptabel mit rund 700, auch bis zu 10.000 threads. Diese Frage wurde im Zusammenhang mit der JVM, aber.

So, lassen Sie uns schätzen, einen fiktiven user-base von rund 5.000 Nutzer. Welcher Ansatz sollte wäre die „gleichzeitige“ ein?

  1. Einem Reaktor Muster alles in einem einzigen thread.
  2. Reaktor-Muster mit einem thread-pool (ungefähr, wie groß Sie schlage vor, den thread-pool werden soll?
  3. Erstellen einen thread pro Verbindung und dann die Zerstörung der thread die Verbindung schließt.

Gebe ich zu option 2 klingt nach der besten Lösung für mich, aber ich bin sehr grün in all dies, so dass ich vielleicht ein bisschen naiv und es fehlten einige offensichtliche Fehler. Auch, es klingt wie es sein könnte ziemlich schwer umzusetzen.

PS: ich überlege, mit POCO C++ Libraries. Was darauf hindeutet, alternative Bibliotheken (wie boost) ist in Ordnung mit mir. Allerdings sagen viele POCO-Bibliothek ist sehr einfach und sauber zu verstehen. Also würde ich bevorzugt verwenden, damit ich lernen kann, über die wies, was ich mit.

InformationsquelleAutor omninonsense | 2013-01-14

5 Kommentare

  1. 12

    Reaktive Anwendungen sicherlich bessere Skalierung auf, wenn Sie richtig geschrieben sind. Dies bedeutet

    • Nie Blockierung in eine reaktive thread:
      • Nicht blockiert wird ernsthaft beeinträchtigen die Leistung des Servers, die Sie verwenden in der Regel eine kleine Anzahl von reaktiven threads, also die Blockierung kann auch schnell zu Deadlocks führen.
      • Keine mutexs, da diese blockiert werden können, also kein shared mutable state. Wenn Sie benötigen freigegebenen Zustand müssen Sie wickeln Sie es mit einem Schauspieler oder ähnliches, so dass nur ein thread Zugriff auf den Staat.
    • Alle arbeiten in der reaktiven threads soll die cpu gebunden
      • Alle IO zu sein, asynchron-oder durchgeführt werden, in einem anderen thread-pool und die Ergebnisse wieder in den Reaktor.
      • Dies bedeutet entweder futures oder Rückrufe zu verarbeiten, Antworten, diese Art von code kann schnell zu wartbaren, wenn Sie es nicht gewöhnt ist und diszipliniert werden.
    • Alle arbeiten in der reaktiven threads sollte klein sein
      • Zu pflegen Reaktionsfähigkeit der server alle Aufgaben, die in den Reaktor muss klein sein (begrenzt durch Zeit)
      • Auf einem 8-core-Maschine, die Sie nicht können nicht zulassen, dass 8 lange Aufgaben zur gleichen Zeit eintreffen, weil keine andere Arbeit beginnen, bis Sie komplett sind
      • Wenn eine der Aufgaben könnte eine lange Zeit dauern, es muss aufgebrochen werden (kooperatives multitasking)

    Aufgaben in reaktiven Anwendungen sind geplant, die von der Anwendung nicht vom Betriebssystem, das ist, warum Sie können schneller sein und weniger Speicher. Wenn Sie schreiben eine Reaktive Anwendung, die Sie sagen, Sie kennen das problem-Domäne, so gut, dass Sie können organisieren und planen Sie diese Art von Arbeit besser ist, als das Betriebssystem einplanen können threads, die die gleiche Arbeit in einer blocking-Mode.

    Ich bin ein großer fan von reaktiven Architekturen, aber Sie kommen mit den Kosten. Ich bin nicht sicher, ob ich schreiben würde, mein erstes c++ – Anwendung als reaktive, normalerweise versuche ich zu lernen, eine Sache zu einer Zeit.

    Wenn Sie sich entscheiden, eine reaktive Architektur verwenden Sie einen guten Rahmen, das wird Ihnen helfen, entwerfen und strukturieren Sie Ihren code oder Sie werden am Ende mit spaghetti. Dinge zu suchen sind:

    • Was ist die Einheit der Arbeit?
    • Wie einfach ist es neue Arbeit? kann es nur kommen von einem externen Ereignis (z.B. Netzwerk Anfrage)
    • Wie es einfach ist, zu brechen, die Arbeit in kleinere Stücke?
    • Wie einfach ist es zu verarbeiten, werden die Ergebnisse dieser Arbeit?
    • Wie einfach ist es, sich zu bewegen blockierenden code zu einem anderen thread-pool-und-still-Verfahren die Ergebnisse?

    Empfehlen kann ich eine C++ – Bibliothek für diese, nun mache ich meinen server Entwicklung in Scala und Akka, die alle mit einem ausgezeichneten composable futures-Bibliothek zu halten den code sauber.

    Besten Glück lernen C++ und mit dem je Wahl, die Sie machen.

  2. 7

    Option 2 wird die meisten effizient besetzen Sie Ihre hardware. Hier ist der klassische Artikel, zehn Jahre alt, aber immer noch gut.

    http://www.kegel.com/c10k.html

    Die beste Bibliothek-Kombination in diesen Tagen für die Strukturierung einer Anwendung mit Parallelität und asynchrone warten Boost Thread-plus-Boost-ASIO. Sie könnten auch versuchen, eine C++11 std thread Bibliothek, und std mutex (aber Boost ASIO ist besser als es in vielen Fällen einfach immer Rückruf der gleiche thread und Sie brauchen nicht geschützten Regionen). Bleiben Sie Weg von std future werden, weil es kaputt ist:

    http://bartoszmilewski.com/2009/03/03/broken-promises-c0x-futures/

    Die optimale Anzahl von threads im thread-pool ein thread pro CPU-Kern. 8-Kerne -> 8 threads. Plus vielleicht ein paar zusätzliche, wenn Sie denken, es ist möglich, dass der threadpool-threads nennen könnte blockierenden Operationen manchmal.

    • std future ist nicht kaputt!! C++11 ist, nur fehlt eine Funktion, um leicht Komponieren. In anderen Worten, std future ist ganz gut, aber mit Sie gründlich und effektiv könnte, in manchen Fällen nicht so einfach, wie es sein sollte. Das heißt, +1 unabhängig 😛
  3. 1

    Denke ich, dass option 2 ist die beste. Als für die Optimierung der pool-Größe, ich denke, der pool sollte sein adaptive. Es sollte in der Lage sein, um zu laichen mehrere threads (mit einigen high-hart an der Grenze) und die überflüssige threads in Zeiten geringer Aktivität.

  4. 1

    als die Analogie, die Sie im Zusammenhang mit (und die Kommentare) vorschlagen. dies ist etwas abhängig von der Anwendung. nun, was Sie hier bauen, ist ein Spiel-server. wir analysieren das.

    Spiel-Server (in der Regel) eine Menge von I/O und relativ wenige Berechnungen, so sind Sie weit von einer 100% – CPU-Anwendungen.
    auf der anderen Seite, die Sie in der Regel auch eine änderung der Werte in einer Datenbank (eine „Spiel-Welt“ – Modell). alle Spieler erstellen, liest und schreibt auf diese Datenbank. das ist genau die Schnittmenge problem in der Analogie.

    so, während Sie kann erhalten von der Handhabung der I/O in separaten threads, Sie verlieren auch aus separaten threads greifen auf die gleiche Datenbank und wartet auf seine Schleusen.

    also entweder option 1 oder 2 sind akzeptabel in Ihrer situation. aus Gründen der Skalierbarkeit würde ich nicht empfehlen, die option 3.

Kostenlose Online-Tests