Um leistungsstarke gleichzeitige Server zu erlernen, plane ich, die Implementierung von Nginx zu untersuchen. Gemäß der Konvention müssen Sie zu Beginn ein Hallo-Welt-Programm schreiben. Der nächste Schritt besteht darin, vorzustellen, wie man ein einfaches HTTP-Modul schreibt, um „Hallo Welt“ unter dem Nginx-Framework zu drucken.
Definieren der Verarbeitung von Hallo-Konfigurationselementen
Zuerst müssen wir ein Befehlsarray definieren, um die Konfigurationsdateiparameter des Moduls zu definieren. Jedes Array-Element ist vom Typ ngx_command_t und das Ende des Arrays wird mit ngx_null_command abgeschlossen.
Wenn Nginx ein Konfigurationselement in der Konfigurationsdatei analysiert, durchläuft es zunächst alle Module. Für jedes Modul durchläuft es das Befehlsarray. Jede ngx_command_t-Struktur definiert ein Konfigurationselement, an dem sie interessiert ist. Die Struktur ist wie folgt definiert:
<code><span>struct</span> ngx_command_s { <span>/* 配置项名称 */</span> ngx_str_t name; <span>/* 指定配置项可以出现的位置 */</span> ngx_uint_t type; <span>/* 出现了name中指定的配置项后,将会调用set方法处理配置项的参数 */</span><span>char</span> *(*<span>set</span>)(ngx_conf_t *cf, ngx_command_t *cmd, <span>void</span> *conf); ngx_uint_t conf; <span>/* 在配置文件中的偏移量 */</span> ngx_uint_t offset; <span>/* 配置项读取后的处理过程,必须是ngx_conf_post_t结构的指针 */</span><span>void</span> *post; }; <span>#define ngx_null_command { ngx_null_string, 0, NULL, 0, 0, NULL }</span></code>
Nachdem wir das Befehlsarray verstanden haben, definieren wir die Verarbeitung des Hallo-Konfigurationselements:
<code><span>static</span> ngx_command_t ngx_http_hello_commands[] = { { ngx_string(<span>"hello"</span>), NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, ngx_http_hello, NGX_HTTP_LOC_CONF_OFFSET, <span>0</span>, NULL }, ngx_null_command };</code>
Unter diesen ist ngx_http_hello das Set-Mitglied in die ngx_command_t-Struktur Wenn das Hello-Konfigurationselement in einem bestimmten Konfigurationsblock erscheint, ruft Nginx die ngx_http_hello-Methode auf. Das Folgende ist die Implementierung von ngx_http_hello:
<code><span>static</span><span>char</span> * ngx_http_hello(ngx_conf_t *cf, ngx_command_t *cmd, <span>void</span> *conf) { ngx_http_core_loc_conf_t *clcf; <span>/* 首先找到hello配置项所属的配置块 */</span> clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); <span>/* HTTP框架在处理用户请求进行到NGX_HTTP_CONTENT_PHASE阶段时 * 如果请求的主机域名、URI与hello配置项所在的配置块相匹配 * 则调用ngx_http_hello_handler方法处理这个请求 */</span> clcf->handler = ngx_http_hello_handler; <span>return</span> NGX_CONF_OK; }</code>
Hallo-Modul definieren
Die Art und Weise, ein HTTP-Modul zu definieren, ist sehr einfach. Definieren Sie einfach eine ngx_moodule_t-Struktur wie folgt:
<code>ngx_module_t ngx_http_hello_module = { NGX_MODULE_V1, &ngx_http_hello_module_ctx, <span>/* module context */</span> ngx_http_hello_commands, <span>/* module directives */</span> NGX_HTTP_MODULE, <span>/* module type */</span> NULL, <span>/* init master */</span> NULL, <span>/* init module */</span> NULL, <span>/* init process */</span> NULL, <span>/* init thread */</span> NULL, <span>/* exit thread */</span> NULL, <span>/* exit process */</span> NULL, <span>/* exit master */</span> NGX_MODULE_V1_PADDING };</code>
Das Hello-Modul wird während der Kompilierung zum globalen Array ngx_modules hinzugefügt.
wobei ngx_http_hello_commands
die Verarbeitung des Hello-Konfigurationselements ist, das wir im vorherigen Abschnitt definiert haben.
Da wir das HTTP-Modul definieren, muss type
auf NGX_HTTP_MODULE
gesetzt sein.
Es gibt auch ein wichtiges Mitglied void* ctx
Für das HTTP-Modul muss der ctx-Zeiger auf die ngx_http_module_t
-Schnittstelle zeigen.
Das HTTP-Framework definiert 8 Stufen, die von der Schnittstelle ngx_http_module_t beim Lesen und Neuladen der Konfigurationsdatei beschrieben werden. Wenn das HTTP-Framework gestartet wird, ruft es in jeder Stufe die entsprechende Methode in ngx_http_module_t auf. Wenn keine Arbeit erforderlich ist, kann sie als NULL definiert werden. Da das Hello-Modul keine Arbeit leisten muss, ist es wie folgt definiert:
<code><span>static</span> ngx_http_module_t ngx_http_hello_module_ctx = { NULL, <span>/* preconfiguration */</span> NULL, <span>/* postconfiguration */</span> NULL, <span>/* create main configuration */</span> NULL, <span>/* init main configuration */</span> NULL, <span>/* create server configuration */</span> NULL, <span>/* merge server configuration */</span> NULL, <span>/* create location configuration */</span> NULL <span>/* merge location configuration */</span> };</code>
Benutzeranfragen verarbeiten
Der letzte Schritt besteht darin, Benutzeranfragen zu verarbeiten. Dies erfordert einige Kenntnisse HTTP. Weitere Informationen finden Sie unter Einführung in das HTTP-Protokoll. Wir bearbeiten Benutzeranfragen, indem wir die Methode ngx_http_hello_handler
implementieren, die wie folgt definiert ist:
<code><span>static</span> ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r)</code>
wobei die Struktur ngx_http_request_t
alle angeforderten Informationen enthält (z. B. Methode, URI, Protokollversionsnummer und Header). , usw.), darüber hinaus enthält es auch viele andere Mitglieder, wie z. B. Speicherpool, Antwortheader usw.
Da wir uns nur mit der GET-Methode und der HEAD-Methode befassen, müssen wir die folgenden Urteile fällen:
<code><span>if</span> (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) { <span>return</span> NGX_HTTP_NOT_ALLOWED; }</code>
Als nächstes, da wir den Paketkörper in der Anfrage nicht benötigen , wir müssen den Paketkörper verwerfen, Methode Wie folgt:
<code>ngx_int_t rc = ngx_http_discard_request_body(r); <span>if</span> (rc != NGX_OK) { <span>return</span> rc; }</code>
Dann legen Sie das zurückgegebene Antwortpaket fest. Der zurückgegebene Paketkörper enthält nur eine „Hello World“-Zeichenfolge:
<code>ngx_str_type = ngx_string(<span>"text/plain"</span>); ngx_str_response = ngx_string(<span>"Hello World"</span>); r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = response.len; r->headers_out.content_type = type;</code>
Zuletzt der Header des gesendeten Antwortpakets und der Pakettext:
<code> rc = ngx_http_send_header(r); <span>if</span> (rc == NGX_ERR || rc > NGX_OK || r->header_only) { <span>return</span> rc; } ngx_buf_t *b; b = ngx_create_temp_buf(r->pool, response.len); <span>if</span> (b == NULL) { <span>return</span> NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_memcpy(b->pos, response.data, response.len); b->last = b->pos + response.len; b->last_buf = <span>1</span>; ngx_chain_t out; out.buf = b; out.next = NULL; <span>/* send the buffer chain of your response */</span><span>return</span> ngx_http_output_filter(r, &out);</code>
Der vollständige Code kann hier angezeigt werden: hello_module
Kompilieren und ausführen
Neues erstellen config
Datei im selben Verzeichnis wie der Code und fügen Sie diese ein paar Zeilen hinzu:
<code>ngx_addon_name=ngx_http_hello_module HTTP_MODULES=<span>"<span>$HTTP_MODULES</span> ngx_http_hello_module"</span> NGX_ADDON_SRCS=<span>"<span>$NGX_ADDON_SRCS</span><span>$ngx_addon_dir</span>/ngx_http_hello_module.c"</span></code>
Geben Sie dann das Stammverzeichnis des Nginx-Quellcodes ein, führen Sie configure
aus und denken Sie daran, den Parameter –add-module mitzubringen , und folgen Sie dem Parameter mit dem Pfad zum HTTP-Modulcode, den wir selbst geschrieben haben:
<code>./configure --prefix=<span>/usr/local</span><span>/nginx --add-module=/code</span><span>/nginx-1.8.0/src</span><span>/http/hello</span>_module</code>
Nachdem die Konfiguration abgeschlossen ist, verwenden Sie den Befehl make
zum Kompilieren. Geben Sie nach erfolgreicher Kompilierung make install
ein, um den Vorgang abzuschließen die Installation.
Ändern Sie /usr/local/nginx/conf/nginx.conf
und fügen Sie Folgendes hinzu:
<code>http{ <span>...</span> server { <span>...</span> location /hello { hello; } <span>...</span> } <span>...</span> }</code>
Führen Sie Nginx aus und geben Sie dann IP/hello
in den Browser ein, um die angezeigte „Hello World-Zeichenfolge“ anzuzeigen.
Referenz
"Detailliertes Verständnis von Nginx"
Das Obige stellt das Schreiben des Hallo-Moduls vor, einschließlich inhaltlicher Aspekte. Ich hoffe, es wird für Freunde hilfreich sein, die sich für PHP-Tutorials interessieren.