Beispielanalyse der Listen-Direktive in Nginx

Beispielanalyse der Listen-Direktive in Nginx

Handlungsüberblick

Im vorherigen Artikel haben wir den Analyseprozess der Standortanweisung analysiert. Lassen Sie uns diesen Inhalt kurz überprüfen: Jeder Standort entspricht einer ngx_http_core_loc_conf_t-Struktur, und alle Standorte sind über eine bidirektionale Warteschlange miteinander verbunden. Die Datenstruktur ist relativ komplex.

Die Listen-Direktive

Als leistungsstarker HTTP-Server ist die Netzwerkverarbeitung der Kern von nginx. Wenn Sie die Netzwerkinitialisierung verstehen, können Sie Ihr Verständnis der Netzwerkverarbeitung von nginx vertiefen. Es gibt zwei wichtige netzwerkbezogene Konfigurationsbefehle: „listen“ und „server_name“. Der Listen-Befehl legt die Nginx-Abhöradresse fest. Beim IP-Protokoll ist diese Adresse Adresse und Port. Beim UNIX-Domain-Socket-Protokoll ist diese Adresse Pfad. Ein Listen-Befehl kann nur eine Adresse oder einen Port angeben. Die Adresse kann auch ein Hostname sein.

Ausgehend von diesem Artikel analysieren wir den Analyseprozess der Listen-Direktive. Die Konfiguration der Listen-Direktive ist wie folgt: Aus dem Handbuch von nginx.org können wir die Verwendung von Listen entnehmen:

Abhöradresse[:Port] [Standardserver] [setfib=Nummer] [Backlog=Nummer] [rcvbuf=Größe] [sndbuf=Größe] [accept_filter=Filter] [verschoben] [binden] [ipv6only=an|aus] [ssl] [so_keepalive=an|aus|[keepidle]:[keepintvl]:[keepcnt]];

Die von einer Listen-Anweisung übertragenen Parameter sind sehr komplex. Allerdings schenken wir diesen weniger häufig verwendeten Parametern im Allgemeinen wenig Beachtung. Im Folgenden sind einige gängige Konfigurationsmethoden aufgeführt:

hören Sie 127.0.0.1:8000;
Hören Sie 127.0.0.1, ohne den Port hinzuzufügen, der Standard-Abhörport ist 80;
hören 8000
hören *:8000
listen localhost:8000

Analysieren Sie die URI und den Port in der Listen-Direktive

Aus dem obigen Inhalt wissen wir, dass Listen mehrere Verwendungszwecke hat. Beim Parsen müssen wir die Portnummer und den URI-Teil der Listen-Direktive abrufen. Nginx bietet die Methode ngx_parse_url() zum Parsen von URI und Port. Diese Funktion wird beim Parsen der Listen-Direktive aufgerufen.

ngx_int_t
ngx_parse_url(ngx_pool_t *Pool, ngx_url_t *u)
{
 u_char *p;
 Größe_t Länge;

 p = u->url.data;
 Länge = u->url.länge;
 // Hier ist das Protokoll zum Parsen der Unix-Domäne if (len >= 5 && ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
 gibt ngx_parse_unix_domain_url(Pool, u) zurück;
 }
 // IPV6-Protokoll analysieren if (len && p[0] == '[') {
 gibt ngx_parse_inet6_url(Pool, u) zurück;
 }
 // IPV4-Protokoll analysieren return ngx_parse_inet_url(pool, u);
}

Wir verwenden das IPV4-Protokoll, hier analysieren wir die Funktion ngx_parse_inet_url()

// u.url = "80";
// u.listen = 1;
// u.default_port = 80;
statisches ngx_int_t
ngx_parse_inet_url(ngx_pool_t *Pool, ngx_url_t *u)
{
 u_char *p, *Host, *Port, *Letzter, *URI, *Argumente;
 Größe_t Länge;
 ngx_int_t n;
 Struktur sockaddr_in *sin;
#wenn (NGX_HAVE_INET6)
 Struktur sockaddr_in6 *sin6;
#endif

 u->socklen = sizeof(Struktur sockaddr_in);
 sin = (Struktur sockaddr_in *) &u->sockaddr;
 sin->sin_family = AF_INET; //IPV4-Typ u->family = AF_INET; 

 Host = u->URL.Daten; // "80"

 last = host + u->url.len; // Die Position des letzten Zeichens des Hosts port = ngx_strlchr(host, last, ':'); // Port suchen, hier ist NULL

 uri = ngx_strlchr(host, last, '/'); // URI suchen, hier ist NULL

 args = ngx_strlchr(host, last, '?'); // Suche den Parameter args, der hier NULL ist

 wenn (Argumente) {
 wenn (uri == NULL || args < uri) {
 uri = Argumente;
 }
 }

 wenn (uri) {
 wenn (u->listen || !u->uri_part) {
 u->err = "ungültiger Host";
 gib NGX_ERROR zurück;
 }

 u->uri.len = letzte - uri;
 u->uri.data = uri;

 letzte = uri;

 wenn (uri < port) {
 Port = NULL;
 }
 }

 wenn (Port) {
 Hafen++;

 Länge = letzter - Port;

 n = ngx_atoi(Port, Länge);

 wenn (n < 1 || n > 65535) {
 u->err = "ungültiger Port";
 gib NGX_ERROR zurück;
 }

 u->port = (Eingangsport_t) n;
 sin->sin_port = htons((in_port_t) n);

 u->port_text.len = Länge;
 u->port_text.data = Port;

 letzte = Port - 1;

 } anders {
 wenn (uri == NULL) {

 wenn (u->listen) {

 /* Testwert nur als Port */

 n = ngx_atoi(Host, letzter - Host);

 wenn (n != NGX_ERROR) {

 wenn (n < 1 || n > 65535) {
 u->err = "ungültiger Port";
 gib NGX_ERROR zurück;
 }

 u->port = (Eingangsport_t) n;
 sin->sin_port = htons((in_port_t) n);

 u->port_text.len = letzter - Host;
 u->port_text.data = Host;

 u->Platzhalter = 1;

 gib NGX_OK zurück;
 }
 }
 }

 u->kein_port = 1;
 u->port = u->Standardport;
 sin->sin_port = htons(u->Standardport);
 }

 Länge = letzter - Host;

 wenn (Länge == 0) {
 u->err = "kein Host";
 gib NGX_ERROR zurück;
 }

 u->host.len = Länge;
 u->host.data = Host;

 wenn (u->listen && len == 1 && *host == '*') {
 sin->sin_addr.s_addr = INADDR_ANY;
 u->Platzhalter = 1;
 gib NGX_OK zurück;
 }

 sin->sin_addr.s_addr = ngx_inet_addr(Host, Länge);

 wenn (sin->sin_addr.s_addr != INADDR_NONE) {

 wenn (sin->sin_addr.s_addr == INADDR_ANY) {
 u->Platzhalter = 1;
 }

 u->naddrs = 1;

 u->addrs = ngx_pcalloc(Pool, Größe von(ngx_addr_t));
 wenn (u->addrs == NULL) {
 gib NGX_ERROR zurück;
 }

 sin = ngx_pcalloc(Pool, Größe von(Struktur sockaddr_in));
 wenn (sin == NULL) {
 gib NGX_ERROR zurück;
 }

 ngx_memcpy(sin, &u->sockaddr, Größe von(Struktur sockaddr_in));

 u->addrs[0].sockaddr = (Struktur sockaddr *) sin;
 u->addrs[0].socklen = sizeof(Struktur sockaddr_in);

 p = ngx_pnalloc(Pool, u->Host.Len + Sizeof(":65535") - 1);
 wenn (p == NULL) {
 gib NGX_ERROR zurück;
 }

 u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
  &u->Host, u->Port) – p;
 u->Adresse[0].name.data = p;

 gib NGX_OK zurück;
 }

 wenn (u->keine_Lösung) {
 gib NGX_OK zurück;
 }

 wenn (ngx_inet_resolve_host(pool, u) != NGX_OK) {
 gib NGX_ERROR zurück;
 }

 u->Familie = u->Adresse[0].sockaddr->sa_Familie;
 u->socklen = u->addrs[0].socklen;
 ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen);

 Schalter (u->Familie) {

#wenn (NGX_HAVE_INET6)
 Fall AF_INET6:
 sin6 = (Struktur sockaddr_in6 *) &u->sockaddr;

 wenn (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 u->Platzhalter = 1;
 }

 brechen;
#endif

 Standard: /* AF_INET */
 sin = (Struktur sockaddr_in *) &u->sockaddr;

 wenn (sin->sin_addr.s_addr == INADDR_ANY) {
 u->Platzhalter = 1;
 }

 brechen;
 }

 gib NGX_OK zurück;
}

Diese Funktion analysiert die Adresse und Portnummer unseres Abhörgeräts. In unserer Konfigurationsdatei ist die Portnummer 80 und es ist keine Abhöradresse konfiguriert, daher ist u->wildcard = 1, was bedeutet, dass dies ein Platzhalter ist und wir diese Portnummer aller IP-Adressen des Servers abhören möchten.

Analysieren der Listen-Direktive

Werfen wir einen Blick auf die Listenkonfiguration aus dem Quellcode:

{ 
 ngx_string("hören"),
 NGX_HTTP_SRV_CONF|NGX_CONF_1MEHR,
 ngx_http_core_listen,
 NGX_HTTP_SRV_CONF_OFFSET,
 0,
 NULL 
}

Aus der Konfigurationsdatei können wir erkennen, dass „listen“ nur im Servermodul erscheinen kann und mehrere Parameter haben kann.

Die entsprechende Verarbeitungsfunktion ist ngx_http_core_listen. Lassen Sie uns diese Funktion analysieren. Wir haben einige Codes zur Fehlerbeurteilung gelöscht.

statisches Zeichen *
ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
 ngx_http_core_srv_conf_t *cscf = conf;

 ngx_str_t *Wert, Größe;
 ngx_url_t u;
 ngx_uint_t n;
 ngx_http_listen_opt_t lsopt;

 cscf->listen = 1;

 Wert = cf->args->elts;

 ngx_memzero(&u, Größe von(ngx_url_t));

 u.url = Wert[1];
 u.listen = 1;
 u.Standardport = 80;

 wenn (ngx_parse_url(cf->pool, &u) != NGX_OK) {
 gib NGX_CONF_ERROR zurück;
 }

 ngx_memzero(&lsopt, Größe von(ngx_http_listen_opt_t));

 ngx_memcpy(&lsopt.sockaddr.sockaddr, &u.sockaddr, u.socklen);

 lsopt.socklen = u.socklen;
 lsopt.backlog = NGX_LISTEN_BACKLOG;
 lsopt.rcvbuf = -1;
 lsopt.sndbuf = -1;
#wenn (NGX_HAVE_SETFIB)
 lsopt.setfib = -1;
#endif
#wenn (NGX_HAVE_TCP_FASTOPEN)
 lsopt.fastopen = -1;
#endif
 lsopt.wildcard = u.wildcard;
#wenn (NGX_HAVE_INET6)
 lsopt.ipv6only = 1;
#endif

 (leer) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, lsopt.addr,
  NGX_SOCKADDR_STRLEN, 1);

 für (n = 2; n < cf->args->nelts; n++) {

 wenn (ngx_strcmp(Wert[n].data, "Standardserver") == 0
 || ngx_strcmp(Wert[n].data, "Standard") == 0)
 {
 lsopt.default_server = 1;
 weitermachen;
 }
 // Die anderen Codes hier dienen alle zur Verarbeitung verschiedener Parameter von listen, die für unsere Analyse hier nutzlos sind}

 wenn (ngx_http_add_listen(cf, cscf, &lsopt) == NGX_OK) {
 gib NGX_CONF_OK zurück;
 }

 gib NGX_CONF_ERROR zurück;
}

Der Gesamtprozess dieser Funktion besteht darin, die verschiedenen Parameter der Listenanweisung zu analysieren und ein ngx_http_listen_opt_t zu generieren. Wie der Name schon sagt, wird diese Struktur verwendet, um einige Listening-Port-Optionen (Listening-Port-Option) zu speichern. Hier wird eine Funktion ngx_parse_url() aufgerufen. Wir haben sie oben analysiert. Die Funktion dieser Funktion besteht darin, die Adresse und den Port in der URL zu analysieren.

Dann kommt der wichtigste Teil. Die Funktion ngx_http_core_listen() ruft am Ende die Funktion ngx_http_add_listen() auf, die die Abhörportinformationen im dynamischen Port-Array der Struktur ngx_http_core_main_conf_t speichert.

Funktion ngx_http_add_listen()

// cf: Konfigurationsstruktur // cscf: Konfigurationsstruktur des Servers, auf dem sich die Listen-Direktive befindet // lsopt: Listen-Option, generiert durch ngx_http_core_listen()
ngx_int_t
ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
 ngx_http_listen_opt_t *lsopt)
{
 in_port_t p;
 ngx_uint_t ich;
 Struktur sockaddr *sa;
 ngx_http_conf_port_t *Port;
 ngx_http_core_main_conf_t *cmcf;
 // Holen Sie sich die main_conf-Struktur des Moduls ngx_http_core_module ngx_http_core_main_conf_t
 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
 // Das Feld „Ports“ ist ein Array, wenn (cmcf->ports == NULL) {
  cmcf->ports = ngx_array_create(cf->temp_pool, 2,
          Größe von (ngx_http_conf_port_t));
  wenn (cmcf->ports == NULL) {
   gib NGX_ERROR zurück;
  }
 }

 sa = &lsopt->sockaddr.sockaddr;
 p = ngx_inet_get_port(sa);

 Port = cmcf->Ports->elts;
 für (i = 0; i < cmcf->ports->nelts; i++) {

  wenn (p != port[i].port || sa->sa_family != port[i].family) {
   weitermachen;
  }

  /* ein Port ist bereits in der Portliste */

  gibt ngx_http_add_addresses zurück (cf, cscf, &port[i], lsopt);
 }

 /* einen Port zur Portliste hinzufügen */

 Port = ngx_array_push(cmcf->ports);
 wenn (Port == NULL) {
  gib NGX_ERROR zurück;
 }

 port->Familie = sa->sa_familie;
 Port->Port = p;
 port->adressen.elts = NULL;

 gibt ngx_http_add_address(cf, cscf, port, lsopt) zurück;
}

Diese Funktion speichert die Portnummerninformationen im Portfeld der Struktur ngx_http_core_main_conf_t.

Zusammenfassen

Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Lernwert für Ihr Studium oder Ihre Arbeit hat. Wenn Sie Fragen haben, können Sie eine Nachricht hinterlassen. Vielen Dank für Ihre Unterstützung von 123WORDPRESS.COM.

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung der Anweisungen zur Nginx-Protokollkonfiguration
  • Priorität und Sicherheitsprobleme bei der Standortübereinstimmung der Nginx-Konfigurationsrichtlinie
  • Hinweise zur Verwendung der nginx proxy_pass-Direktive '/'
  • Detaillierte Erläuterung der Aktivierungs- und Konfigurationsanweisungen für das Nginx Gzip-Modul
  • Die Anweisung nginx try_files ermittelt, ob eine Datei existiert
  • So verwenden Sie die nginx add_header-Direktive
  • Allgemeine Anweisungen zur Konfiguration des Nginx-HTTP-Moduls
  • Verwenden des Map-Befehls von Nginx zum Umleiten von Seiten
  • Eine kurze Analyse des Unterschieds zwischen den Root- und Alias-Direktiven in der Nginx-Konfiguration
  • Detaillierte Erläuterung der Nginx SSI-Direktivenkonfiguration

<<:  Mysql, einige komplexe SQL-Anweisungen (Abfragen und Löschen doppelter Zeilen)

>>:  Ausführliche Erläuterung des globalen Status des WeChat-Applets

Artikel empfehlen

jQuery erzielt Vollbild-Scrolling-Effekt

In diesem Artikelbeispiel wird der spezifische Co...

Webdesign-Tutorial (7): Verbesserung der Webdesign-Effizienz

<br />Vorheriger Artikel: Webdesign-Tutorial...

Bootstrap 3.0-Lernunterlagen für Anfänger

Als ersten Artikel dieser Studiennotiz beginnen w...

So kompilieren Sie Nginx neu und fügen Module hinzu

Beim Kompilieren und Installieren von Nginx werde...

So verwenden Sie Cursor-Trigger in MySQL

Cursor Die von der Auswahlabfrage zurückgegebenen...

Erste Erfahrungen mit der Texterstellung mit Javascript Three.js

Inhaltsverzeichnis Wirkung Beginnen Sie mit der T...

Zusammenfassung der wichtigsten Erkenntnisse des Vue-Entwicklungshandbuchs

Inhaltsverzeichnis Überblick 0. Grundlagen von Ja...

Das WeChat-Applet implementiert feste Header- und Listentabellenkomponenten

Inhaltsverzeichnis brauchen: Funktionspunkte Rend...