1. Grundkenntnisse
1.1 Swoole
Swoole ist eine asynchrone PHP-Netzwerkkommunikations-Engine für Produktionsumgebungen, mit der PHP-Entwickler leistungsstarke Serverdienste entwickeln können. Der Serverteil von Swoole ist umfangreich und beinhaltet viele Wissenspunkte. Dieser Artikel gibt nur einen kurzen Überblick über den Server. Die spezifischen Implementierungsdetails werden in den folgenden Artikeln ausführlich vorgestellt.
Empfohlen (kostenlos): swoole
1.2 Netzwerkprogrammierung
1. Netzwerkkommunikation bezieht sich auf das Starten eines (oder mehrerer) Prozesse auf einer (oder mehreren) Maschinen, die Überwachung eines (oder mehrerer) Ports, Informationen mit dem Client gemäß einem bestimmten Protokoll austauschen (es kann das Standardprotokoll http, dns sein; es kann auch ein selbstdefiniertes Protokoll sein).
2. Der Großteil der aktuellen Netzwerkprogrammierung basiert auf TCP-, UDP- oder höherschichtigen Protokollen. Der Serverteil von Swoole basiert auf den Protokollen TCP und UDP.
3. Die Programmierung mit udp ist relativ einfach. In diesem Artikel wird hauptsächlich die Netzwerkprogrammierung basierend auf dem TCP-Protokoll vorgestellt.
4. Die TCP-Netzwerkprogrammierung umfasst hauptsächlich 4 Arten von Ereignissen.
Verbindungsaufbau: Bezieht sich hauptsächlich auf den Client Initiieren einer Verbindung (Verbinden) und der Server akzeptiert die Verbindung (Akzeptieren)● Eintreffen der Nachricht: Der Server empfängt die vom Client gesendeten Daten Bei dieser Art von Ereignis können Sie blockierende oder nicht blockierende Ereignisse verwenden. Darüber hinaus muss der Server auch Probleme wie Paketierung und Anwendungsschichtpuffer berücksichtigen. Erfolgreiches Senden bedeutet, dass die Anwendungsschicht Die Daten werden erfolgreich an den Socket-Sendepuffer des Kernels gesendet. Dies bedeutet nicht, dass der Client die Daten erfolgreich akzeptiert hat. Bei Diensten mit geringem Datenverkehr können die Daten in der Regel auf einmal gesendet werden, und es besteht kein Grund, sich um solche Ereignisse zu kümmern. Wenn nicht alle Daten auf einmal an den Kernelpuffer gesendet werden können, müssen Sie darauf achten, ob die Nachricht erfolgreich gesendet wird (bei Blockprogrammierung ist das Senden erfolgreich, nachdem der Systemaufruf (write, writev, send usw.) zurückgegeben wurde. Bei der nicht blockierenden Programmierung müssen Sie die tatsächliche Situation berücksichtigen. Ob die geschriebenen Daten mit den Erwartungen übereinstimmen. (Schließen, Herunterfahren)
5. TCP stellt Verbindung her. Der Vorgang ist wie unten dargestellt: ACK und SYN stellen Flag-Bits dar, seq und ack sind die Sequenznummer und Bestätigungssequenznummer des TCP-Pakets 6. Der Prozess der TCP-Verbindungstrennung ist wie unten dargestellt: ● Die obige Abbildung berücksichtigt die Situation, in der der Server die Verbindung aktiv trennt. ● In der Abbildung stellen FIN und ACK dar Flag-Bits, Seq und Ack sind die Sequenznummer und Bestätigungssequenznummer des TCP-Pakets (Signal), Semaphor (Semaphor), Sockets (Socket), Shared Memory (Shared Memory) und andere Methoden
2 Swoole verwendet Unix-Domain-Sockets (eine Art Socket) für die Kommunikation zwischen mehreren Prozessen (bezogen auf interne Swoole-Prozesse).1.4 Socketpair wird verwendet, um ein Socketpaar zu erstellen, ähnlich wie bei Pipe. Der Unterschied besteht darin, dass eine bidirektionale Kommunikation erstellt werden muss Die Kommunikation kann durch einen einmaligen Aufruf von socketpair erreicht werden. Da es sich um einen Socket handelt, können Sie auch die Methode des Datenaustauschs definieren
2. Der Aufruf des Socketpair-Systems ist erfolgreich. sv[0], sv[1] speichern jeweils einen Dateideskriptorin sv[0] Schreiben Sie in sv[1], Sie können von sv[1] lesenSchreiben Sie in sv[1], Sie können von sv lesen [0]
Nachdem der Prozess socketpair aufgerufen hat, gibt er den untergeordneten Prozess ab und der untergeordnete Prozess erbt standardmäßig sv. Die beiden Dateideskriptoren [0] und sv[1] können die Kommunikation zwischen übergeordneten und untergeordneten Prozessen realisieren. Beispielsweise schreibt der übergeordnete Prozess in sv[0] und der untergeordnete Prozess liest von sv[1]; der untergeordnete Prozess schreibt in sv[1] und der übergeordnete Prozess liest von sv[0]
1.5 Daemon
1. Der Daemon ist ein spezieller Hintergrundprozess, der vom Terminal getrennt ist und zur regelmäßigen Ausführung bestimmter Aufgaben verwendet wird
Jeder Prozess gehört zu einer Prozessgruppe
Jede Prozessgruppe hat eine Prozessgruppennummer, die die Prozessnummer (PID) des Gruppenleiters ist. Ein Prozess kann die Prozessgruppennummer nur für sich selbst oder seine untergeordneten Prozesse festlegen
Wenn der obige Code im CLI-Modus ausgeführt wird, wird Opcode durch lexikalische Analyse und Syntaxanalyse generiert und dann zur Ausführung an die virtuelle Zend-Maschine übergeben.
Basismodus Unten hat der Parameter „reaktor_number“ keine praktische Wirkung
Wenn die Anzahl der Arbeitsprozesse auf 1 gesetzt ist, wird der Arbeitsprozess nicht ausgespalten und der Hauptprozess verarbeitet die Anfrage direkt Der Modus eignet sich zum Debuggen
2. Startvorgangphp-Codeausführung Wenn $serv->start() erreicht ist, ruft der Hauptprozess die Funktion int swServer_start(swServer *serv) auf, die für den Start des Servers verantwortlich ist
In der Funktion swServer_start wird swReactorProcess_start aufgerufen. Diese Funktion verteilt mehrere Arbeitsprozesse. Der Master-Prozess und der Arbeitsprozess treten jeweils in eine eigene Ereignisschleife ein, um verschiedene Ereignisse zu verarbeiten. 2.2-Prozessmodus. BeschreibungDer Hauptprozess verzweigt zunächst den Manager-Prozess, und der Manager-Prozess ist für die Verzweigung des Worker-Prozesses und des task_worker-Prozesses verantwortlich. Nachdem der Worker-Prozess in int swWorker_loop
(swServer *serv, int worker_id) eintritt, d Thread, Hauptthread und React Die Threads betreten jeweils ihre eigene Ereignisschleife. Der Reaktorthread führt static int swRea-torThread_loop (swThreadParam *param) aus und wartet auf die Verarbeitung von EreignissenDie obige Abbildung berücksichtigt nicht den task_worker-Prozess. Standardmäßig beträgt die Anzahl der task_worker-Prozesse 0
Drei. Prozessmodus)
3.1 Kommunikation zwischen Reaktor-Thread und Worker-Prozess
1. Die Kommunikation zwischen Swoole-Masterprozess und Worker-Prozess ist wie in der Abbildung unten dargestellt
2. Angenommen, es gibt 2 Reaktor-Threads und 3 Worker-Prozesse, dann der Reaktor und Die Kommunikation zwischen Workern ist in der folgenden Abbildung dargestellt
1 Der Haupt-Thread im Master-Prozess ist für das Abhören des Ports verantwortlich (listen). code>) und das Akzeptieren von Verbindungen (<code>accept
, generiert einen fd). Nach dem Akzeptieren der Verbindung wird die Anforderung dem Reaktorthread zugewiesen. Standardmäßig wird fd % Reaktornummer zugewiesen und dann wird fd hinzugefügt Achten Sie beim ersten Beitritt auf den entsprechenden Reaktorthread über epoll_ctl
. Da der Schreibpuffer des durch die neu akzeptierte Verbindung erstellten Sockets leer ist, muss er beschreibbar sein und wird sofort ausgelöst Dann führt der Reaktor-Thread einige Initialisierungsvorgänge aus.
listen
), 接受连接(accept
, 产生一个fd), 接受连接后将请求分配给reactor线程, 默认通过fd % reactor_number进行分配, 之后通过epoll_ctl
将fd加入到对应reactor线程中, 刚加入时监听写事件, 因为新接受连接创建的套接字写缓冲区为空, 故而一定可写, 会被立刻触发, 进而reactor线程进行一些初始化操作
epoll_create
创建)的情况epoll_ctl
是线程安全的(对应一个epollfd), 一个线程正在执行, 其他线程会被阻塞(因为需要同时操作epoll底层的红黑树)epoll_wait
也是线程安全的, 但是一个事件可能会被多个线程同时接收到, 实际中不建议多个线程同时epoll_wait
一个epollfd。Swoole中也是不存在这种情况的, Swoole中每个reactor线程都有自己的epollfdepoll_wait
, 一个线程调用epoll_ctl
, 根据man手册, 如果epoll_ctl
新加入的fd已经准备好, 会使得执行epoll_wait
的线程变成非阻塞状态(可以通过man epoll_wait
Es gibt mehrere Threads, die gleichzeitig ausgeführt werden. Im Fall eines epollfd (erstellt durch den Systemaufruf epoll_create
) aufrufen epoll_ctl
ist gleichzeitig threadsicher (entspricht einem epollfd), ein Thread wird ausgeführt und andere Threads werden blockiert (da der rot-schwarze Baum, der epoll zugrunde liegt, gleichzeitig betrieben werden muss) Es ist auch threadsicher, wenn mehrere Threads gleichzeitig epoll_wait
aufrufen, aber ein Ereignis kann von mehreren Threads gleichzeitig empfangen werden. In der Praxis wird nicht empfohlen, dass mehrere Threads epoll_wait
epollfd gleichzeitig. Diese Situation existiert in Swoole nicht. Jeder Reaktor-Thread in Swoole hat seinen eigenen epollfd
Ein Thread ruft epoll_wait
auf, und ein anderer Thread ruft epoll_ctl
auf, so das Man-Handbuch. Wenn der neu hinzugefügte fd von epoll_ctl
bereit ist, wird der Thread, der epoll_wait
ausführt, nicht blockierend (Sie können die relevanten Informationen über man epoll_wait
anzeigen). Inhalt)
close
), 则需要先找到监听这个连接的reactor线程, 进而改变这个连接的监听状态(通过调用epoll_ctl
Viertens 4.1 Start im Prozessmodus Modus und Prozess Modus. Es erklärt die Netzwerkprogrammierungsmodelle der beiden Modi im Detail und konzentriert sich auf die prozessübergreifende Kommunikationsmethode, den Anforderungsverarbeitungsablauf usw.
3 Im Prozessmodus kann jeder Reaktorthread im Hauptprozess mehrere Anforderungen gleichzeitig verarbeiten, und mehrere Anforderungen werden gleichzeitig verarbeitet. Wir betrachten es aus zwei Dimensionen
Aus der Perspektive des Hauptprozesses verarbeitet der Hauptprozess mehrere Anfragen gleichzeitig. Wenn alle Anfragepakete empfangen werden, werden sie zur Verarbeitung an den Workerprozess weitergeleitet
Aus der Perspektive eines Worker-Prozesses Aus der Sicht sind die von diesem Worker-Prozess empfangenen Anfragen seriell. Wenn eine einzelne Anfrage blockiert ist (Swooles Worker-Prozess ruft die von PHPer geschriebene Ereignisverarbeitungsfunktion zurück). Diese Funktion kann blockieren. Nachfolgende Anforderungen können nicht verarbeitet werden. In diesem Fall kann die Coroutine von Swool verwendet werden, wenn eine einzelne Anforderung blockiert wird4. Da es sich bei TCP um ein Byte-Stream-Protokoll handelt, kann Swoole keine Unteraufträge vergeben, ohne das Kommunikationsprotokoll zwischen dem Client und dem Server zu kennen Wird vom Reaktor an den Arbeitsprozess übergeben. Es kann nur ein Bytestrom sein und muss vom Benutzer verarbeitet werden. Natürlich ist es im Allgemeinen nicht erforderlich, selbst ein Protokoll zu erstellen, da Swoole bereits HTTP, HTTPS und andere Protokolle unterstützt
Das obige ist der detaillierte Inhalt vonEine kurze Analyse des Swoole-Servers. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!