Java IO Stream (3) Thread-Modell

Traditioneller blockierender E/A-Modus

Das gelbe Feld stellt das Objekt dar, das blaue Feld stellt den Thread dar und das weiße Feld stellt die API-Methode dar.

Merkmale

  • Erhalten Sie Eingabedaten im blockierenden E/A-Modus
  • Für jede Verbindung ist ein unabhängiger Thread erforderlich, um die Dateneingabe, die Geschäftsverarbeitung und die Datenrückgabe der Verarbeitungsergebnisse abzuschließen

potenzielle Probleme

  • Wenn die Anzahl der Parallelitäten groß ist, muss für jede Verbindungsanforderung ein Thread erstellt werden, was viele Ressourcen beansprucht.
  • Wenn der aktuelle Thread nach dem Herstellen der Verbindung vorerst keine Datenoperation ausführt, wird der Thread bei der Operationsmethode blockiert, was zu einer Verschwendung von Thread-Ressourcen führt.

Reaktormodus (Dispatch-Modus)

Um die potenziellen Probleme des herkömmlichen blockierenden E/A-Modus anzugehen, lauten die Lösungen wie folgt:

  • Lösen Sie das Problem der Erstellung einer großen Anzahl von Threads basierend auf dem E/A-Multiplexing-Modell: Verwalten Sie alle Verbindungen über ein Blockierungsobjekt
  • Lösen Sie das Problem der Thread-Ressourcenverschwendung basierend auf dem Thread-Pool

Die Designidee des Reactor-Musters ist die I/O-Wiederverwendung in Kombination mit einem Thread-Pool .

Kernkomponenten

  • Reator: Reactor läuft in einem separaten Thread und ist für das Abhören und Verteilen von Ereignissen an entsprechende Handler verantwortlich, um auf IO-Ereignisse zu reagieren.
  • Handler: Verarbeitet tatsächlich die vom Ausführungsreaktor verteilten E/A-Ereignisse

Vorteil

  • Schnelle Reaktion: keine Blockierung durch einmalige Synchronisierung
  • Gute Skalierbarkeit: Nutzen Sie die Multi-Core-CPU-Ressourcen vollständig aus, indem Sie die Anzahl der Reactor-Instanzen einfach erhöhen
  • Gute Wiederverwendbarkeit: Der Reaktor selbst hat nichts mit einer bestimmten Ereignisverarbeitungslogik zu tun und weist eine hohe Wiederverwendbarkeit auf

Abhängig von der Anzahl der Reaktoren und der Anzahl der Threads des Verarbeitungsressourcenpools umfasst es einen einzelnen Reactor-Einzelthread, einen einzelnen Reactor-Multithread und einen Master-Slave-Reactor-Multithread.

Einzelreaktor -Einzelthread

Umsetzungsprozess
  • Reactor überwacht Clientanforderungsereignisse über Select und verteilt sie über Dispatch, nachdem die Ereignisse empfangen wurden.
  • Wenn es sich um eine Verbindungsanforderung handelt, wird sie vom Akzeptor verarbeitet und ein Handler-Objekt erstellt, um das Geschäft nach Abschluss der Verbindung abzuwickeln.
  • Wenn es sich nicht um eine Verbindungsanforderung handelt (z. B. Lesen), wird der entsprechende Handler zur Antwort gesendet (Lesen->Geschäftsverarbeitung->Sendeprozess).
Fall Analyse
  • Der Modus ist einfach, es gibt keine Multi-Thread-Konkurrenz, alles wird durch einen Thread abgeschlossen
  • Leistungsproblem: Nur ein Thread kann keine Multi-Core-CPU-Leistung erbringen
  • Zuverlässigkeitsprobleme: Eine unerwartete Thread-Beendigung oder eine Endlosschleife führen dazu, dass das System nicht mehr verfügbar ist
  • Geeignet für Szenarien, in denen die Anzahl der Kunden begrenzt ist und die Geschäftsabwicklung sehr schnell erfolgt

Einzelreaktor -Multithreading

Umsetzungsprozess
  • Reactor überwacht Clientanforderungsereignisse über Select und verteilt sie über Dispatch, nachdem die Ereignisse empfangen wurden.
  • Wenn es sich um eine Verbindungsanforderung handelt, wird sie vom Akzeptor verarbeitet und ein Handler-Objekt erstellt, um das Geschäft nach Abschluss der Verbindung abzuwickeln.
  • Wenn es sich nicht um eine Verbindungsanforderung handelt (z. B. Lesen), ruft die Reactor-Verteilung den entsprechenden Handler auf, um zu antworten (Lesen->Verteilungsaufgabe->Sendeprozess).
  • Der Handler ist nur für die Reaktion auf Ereignisse verantwortlich und führt keine spezifische Geschäftsverarbeitung durch . Die gelesenen Daten werden an einen Thread im Arbeitsthread-Pool verteilt , um das Geschäft zu verarbeiten.
  • Der Arbeits-Thread-Pool weist unabhängige Threads zu, um das eigentliche Geschäft abzuschließen und die Ergebnisse an den Handler zurückzugeben
  • Nachdem der Handler die Antwort erhalten hat, sendet er das Ergebnis per Senden an den Client zurück.
Fall Analyse
  • Kann die Rechenleistung einer Multi-Core-CPU voll ausnutzen
  • Die gemeinsame Nutzung und der Zugriff auf Multithread-Daten sind relativ komplex. Reactor übernimmt die gesamte Ereignisüberwachung und Reaktion. In Single-Thread-Szenarien mit hoher Parallelität kann es leicht zu Leistungsengpässen kommen.

Master-Slave-Reaktor-Multithreading (Netty basiert auf diesem Modus)

Umsetzungsprozess
  • Das MainReactor-Objekt des Reactor-Hauptthreads überwacht Verbindungsereignisse über Select. Wenn ein Verbindungsanforderungsereignis empfangen wird, wird es über Acceptor verarbeitet.
  • Wenn der Akzeptor die Verarbeitung des Verbindungsereignisses abschließt, weist der MainReactor die Verbindung dem SubReactor zu ( ein MainReactor verfügt über mehrere Sub-Reactors ).
  • SubReactor fügt die Verbindung zur Überwachung zur Verbindungswarteschlange hinzu und erstellt einen Handler für die entsprechende Ereignisverarbeitung
  • Wenn ein neues Ereignis auftritt, ruft subReactor den entsprechenden Handler zur Verarbeitung auf
  • Der Handler ist nur für die Reaktion auf Ereignisse verantwortlich und führt keine spezifische Geschäftsverarbeitung durch. Die durch Lesen gelesenen Daten werden an einen Thread im Arbeitsthread-Pool verteilt, um das Geschäft zu verarbeiten.
  • Der Arbeits-Thread-Pool weist unabhängige Threads zu, um das eigentliche Geschäft abzuschließen und die Ergebnisse an den Handler zurückzugeben
  • Nachdem der Handler die Antwort erhalten hat, sendet er das Ergebnis per Senden an den Client zurück.
Fall Analyse
  • Die Dateninteraktion zwischen dem Hauptthread und den Unterthreads ist einfach und hat klare Verantwortlichkeiten. Der Hauptthread ist für den Empfang von Verbindungen verantwortlich, und die Unterthreads vervollständigen die nachfolgende Geschäftsverarbeitung.
  • Die Interaktion zwischen dem Hauptthread und dem Unterthread ist einfach: Der Hauptthread übergibt die Verbindung an den Unterthread und der Unterthread muss keine Daten zurückgeben.
  • Allerdings ist der Programmieraufwand relativ hoch
  • Wird auf das Nginx-Master-Slave-Reactor-Multiprozessmodell, das Memcached-Master-Slave-Multithreading und das Netty-Master-Slave-Multithreading angewendet

Supongo que te gusta

Origin blog.csdn.net/qq_34020761/article/details/132388728
Recomendado
Clasificación