Inhaltsverzeichnis
und der Block mailBlock warten. Jeder dieser Konfigurationsblöcke stellt einen Bereich dar. Der Bereich eines Konfigurationsblocks einer höheren Ebene enthält den Bereich mehrerer Konfigurationsblöcke einer niedrigeren Ebene, was das Phänomen der Bereichsverschachtelung darstellt. Auf diese Weise werden viele Anweisungen in der Konfigurationsdatei gleichzeitig in mehrere Bereiche aufgenommen. Beispielsweise können sich die Anweisungen im
wurden initialisiert, bevor das Programm Nginx die Konfigurationsanalysefunktion aufruft, sodass sie nach dem Aufrufen der Konfigurationsanalysefunktion direkt analysiert und in der tatsächlichen Datenstruktur gespeichert werden können Sie beziehen sich auf die Struktur der Konfigurationsdatei und beziehen sich im Allgemeinen auf Anweisungen außerhalb des Konfigurationsblocks, die sich im globalen Blockteil der Konfigurationsdatei befinden. Zu den
Heim Backend-Entwicklung PHP-Tutorial Nginx-Konfigurationsanalyse

Nginx-Konfigurationsanalyse

Aug 08, 2016 am 09:31 AM
conf gt http nbsp

Übersicht

Im vorherigen Artikel „ „Nginx Startup Initialization Process“ stellt kurz den Startvorgang von Nginx vor und analysiert den Quellcode seines Startvorgangs. Es gibt einen sehr wichtigen Schritt im Startvorgang, nämlich den Aufruf der Funktion ngx_init_cycle(). Der Aufruf dieser Funktion stellt eine Schnittstelle für die Konfigurationsanalyse bereit. Die Konfigurationsanalyseschnittstelle kann grob in zwei Phasen unterteilt werden: die Datenvorbereitungsphase und die Konfigurationsanalysephase. Die Datenvorbereitungsphase umfasst:

Speicher vorbereiten
    Fehlerprotokoll vorbereiten;
  • Erforderliche Datenstruktur vorbereiten; ngx_conf_t
  • Struktur
  • Diese Struktur wird von
  • Nginx
verwendet, um die Attribute jeder Direktive beim Parsen zu beschreiben Die Konfigurationsdatei ist auch eine sehr wichtige Datei im

Nginx

-Programm, die in der Datei
    /* 配置文件解析 */  
    if (ngx_conf_param(&conf) != NGX_CONF_OK) {/* 带有命令行参数'-g' 加入的配置 */  
        environ = senv;  
        ngx_destroy_cycle_pools(&conf);  
        return NULL;  
    }  
  
    if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {/* 解析配置文件*/  
        environ = senv;  
        ngx_destroy_cycle_pools(&conf);  
        return NULL;  
    }  
Nach dem Login kopieren
src/core/ngx_conf_file.h

Informationen zur Konfigurationsdateiconf_file

🎜>conf_file dient zum Speichern der relevanten Informationen der Nginx-Konfigurationsdatei. ngx_conf_file_t Die Struktur ist wie folgt definiert:

/* 解析配置时所使用的结构体 */
struct ngx_conf_s {
    char                 *name;     /* 当前解析到的指令 */
    ngx_array_t          *args;     /* 当前指令所包含的所有参数 */

    ngx_cycle_t          *cycle;    /* 待解析的全局变量ngx_cycle_t */
    ngx_pool_t           *pool;     /* 内存池 */
    ngx_pool_t           *temp_pool;/* 临时内存池,分配一些临时数组或变量 */
    ngx_conf_file_t      *conf_file;/* 待解析的配置文件 */
    ngx_log_t            *log;      /* 日志信息 */

    void                 *ctx;      /* 描述指令的上下文 */
    ngx_uint_t            module_type;/* 当前解析的指令的模块类型 */
    ngx_uint_t            cmd_type; /* 当前解析的指令的指令类型 */

    ngx_conf_handler_pt   handler;  /* 模块自定义的handler,即指令自定义的处理函数 */
    char                 *handler_conf;/* 自定义处理函数需要的相关配置 */
};
Nach dem Login kopieren
Konfigurationskontext

ctx

Die Konfigurationsdatei von

Nginx ist Die Konfiguration ist in Chunks unterteilt. Zu den gebräuchlichsten gehören der Block http, der Block server, der Block location

sowie der Block
typedef struct {
    ngx_file_t            file;     /* 文件的属性 */
    ngx_buf_t            *buffer;   /* 文件的内容 */
    ngx_uint_t            line;     /* 文件的行数 */
} ngx_conf_file_t;
Nach dem Login kopieren
upsteam

und der Block mailBlock warten. Jeder dieser Konfigurationsblöcke stellt einen Bereich dar. Der Bereich eines Konfigurationsblocks einer höheren Ebene enthält den Bereich mehrerer Konfigurationsblöcke einer niedrigeren Ebene, was das Phänomen der Bereichsverschachtelung darstellt. Auf diese Weise werden viele Anweisungen in der Konfigurationsdatei gleichzeitig in mehrere Bereiche aufgenommen. Beispielsweise können sich die Anweisungen im

http

-Block gleichzeitig in drei Bereichen befinden: http-Block, Server-Block und Standort Block. Wenn das Programm Nginx die Konfigurationsdatei analysiert, sollte jede Anweisung den Bereich aufzeichnen, zu dem sie gehört, und die Kontextvariable ctx der Konfigurationsdatei wird zum Speichern verwendet current Der Bereich, zu dem die Direktive gehört. Unter den verschiedenen Konfigurationsblöcken der Nginx-Konfigurationsdatei kann der http-Block Unterkonfigurationsblöcke enthalten, was hinsichtlich der Speicherstruktur komplexer ist. AnweisungstypTyp

                                                                                                                                                                                                                         Der Modultyp core ist in der Datei definiert: src/core/ngx_conf_file.h Dies sind die vom Kerntypmodul unterstützten Befehlstypen. Die Klassenanweisungen

NGX_DIRECT_CONF

wurden initialisiert, bevor das Programm Nginx die Konfigurationsanalysefunktion aufruft, sodass sie nach dem Aufrufen der Konfigurationsanalysefunktion direkt analysiert und in der tatsächlichen Datenstruktur gespeichert werden können Sie beziehen sich auf die Struktur der Konfigurationsdatei und beziehen sich im Allgemeinen auf Anweisungen außerhalb des Konfigurationsblocks, die sich im globalen Blockteil der Konfigurationsdatei befinden. Zu den

NGX_MAIN_CONF

-Klassenanweisungen gehören Event, http, Mail,

Upstream
#define NGX_DIRECT_CONF            0x00010000  
#define NGX_MAIN_CONF              0x01000000  
#define NGX_ANY_CONF               0x0F000000 
Nach dem Login kopieren
und andere Anweisungen, die Konfigurationsblöcke bilden können. Verfügt nicht über eine eigene Initialisierungsfunktion. Wenn das Nginx-Programm beim Parsen der Konfigurationsdatei auf die Klassenanweisung NGX_MAIN_CONF stößt, wechselt es zum Parsen der Anweisung der nächsten Ebene. Im Folgenden sind die Anweisungstypen aufgeführt, die vom Typmodul Ereignis unterstützt werden. Im Folgenden sind die vom Typmodul http unterstützten Befehlstypen aufgeführt, die in der Datei definiert sind: src/http/ngx_http_config.hAllgemeine Modulkonfigurationsanalyse Das Konfigurationsanalysemodul ist in Implementiert in src/core/ngx_conf_file.c

. Die vom Modul bereitgestellten Schnittstellenfunktionen sind hauptsächlich ngx_conf_parse. Darüber hinaus stellt das Modul eine weitere separate Schnittstelle

ngx_conf_param
#define NGX_EVENT_CONF            0x02000000 
Nach dem Login kopieren
bereit, die zum Parsen der von der Befehlszeile übergebenen Konfiguration verwendet wird. Diese Schnittstelle ist auch ein Wrapper für

ngx_conf_parse. Schauen wir uns zunächst die Konfigurationsanalysefunktion ngx_conf_parse an, die wie folgt definiert ist:

Wie aus dem Quellcode der Konfigurationsanalysefunktion ersichtlich ist, ist diese Funktion unterteilt in zwei Stufen: Syntaxanalyse und Befehlsanalyse. Die Syntaxanalyse wird durch die Funktion
#define NGX_HTTP_MAIN_CONF          0x02000000  
#define NGX_HTTP_SRV_CONF           0x04000000  
#define NGX_HTTP_LOC_CONF           0x08000000  
#define NGX_HTTP_UPS_CONF           0x10000000  
#define NGX_HTTP_SIF_CONF           0x20000000  
#define NGX_HTTP_LIF_CONF           0x40000000  
#define NGX_HTTP_LMT_CONF           0x80000000  
Nach dem Login kopieren
ngx_conf_read_token()

vervollständigt. Es gibt zwei Methoden zur Befehlsanalyse: Eine ist der integrierte Befehlsanalysemechanismus von

Nginx

; die andere ist ein benutzerdefinierter Befehlsanalysemechanismus. Der benutzerdefinierte Quellcode zum Parsen von Anweisungen lautet wie folgt: Und der integrierte Parsing-Mechanismus von Nginx wird durch die Funktion ngx_conf_handler() implementiert. Seine Definition lautet wie folgt: HTTP Modulkonfigurationsanalyse

Die Hauptstruktur hier ist
/*
 * 函数功能:配置文件解析;
 * 支持三种不同的解析类型:
 * 1、解析配置文件;
 * 2、解析block块设置;
 * 3、解析命令行配置;
 */
char *
ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
{
    char             *rv;
    ngx_fd_t          fd;
    ngx_int_t         rc;
    ngx_buf_t         buf;
    ngx_conf_file_t  *prev, conf_file;
    enum {
        parse_file = 0,
        parse_block,
        parse_param
    } type;

#if (NGX_SUPPRESS_WARN)
    fd = NGX_INVALID_FILE;
    prev = NULL;
#endif

    if (filename) {/* 若解析的是配置文件 */

        /* open configuration file */

        /* 打开配置文件 */
        fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
        if (fd == NGX_INVALID_FILE) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
                               ngx_open_file_n " \"%s\" failed",
                               filename->data);
            return NGX_CONF_ERROR;
        }

        prev = cf->conf_file;

        cf->conf_file = &conf_file;

        if (ngx_fd_info(fd, &cf->conf_file->file.info) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
                          ngx_fd_info_n " \"%s\" failed", filename->data);
        }

        cf->conf_file->buffer = &buf;

        buf.start = ngx_alloc(NGX_CONF_BUFFER, cf->log);
        if (buf.start == NULL) {
            goto failed;
        }

        buf.pos = buf.start;
        buf.last = buf.start;
        buf.end = buf.last + NGX_CONF_BUFFER;
        buf.temporary = 1;

        /* 复制文件属性及文件内容 */
        cf->conf_file->file.fd = fd;
        cf->conf_file->file.name.len = filename->len;
        cf->conf_file->file.name.data = filename->data;
        cf->conf_file->file.offset = 0;
        cf->conf_file->file.log = cf->log;
        cf->conf_file->line = 1;

        type = parse_file;  /* 解析的类型是配置文件 */

    } else if (cf->conf_file->file.fd != NGX_INVALID_FILE) {

        type = parse_block; /* 解析的类型是block块 */

    } else {
        type = parse_param; /* 解析的类型是命令行配置 */
    }


    for ( ;; ) {
        /* 语法分析函数 */
        rc = ngx_conf_read_token(cf);

        /*
         * ngx_conf_read_token() may return
         *
         *    NGX_ERROR             there is error
         *    NGX_OK                the token terminated by ";" was found
         *    NGX_CONF_BLOCK_START  the token terminated by "{" was found
         *    NGX_CONF_BLOCK_DONE   the "}" was found
         *    NGX_CONF_FILE_DONE    the configuration file is done
         */

        if (rc == NGX_ERROR) {
            goto done;
        }

        /* 解析block块设置 */
        if (rc == NGX_CONF_BLOCK_DONE) {

            if (type != parse_block) {
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\"");
                goto failed;
            }

            goto done;
        }

        /* 解析配置文件 */
        if (rc == NGX_CONF_FILE_DONE) {

            if (type == parse_block) {
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "unexpected end of file, expecting \"}\"");
                goto failed;
            }

            goto done;
        }

        if (rc == NGX_CONF_BLOCK_START) {

            if (type == parse_param) {
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "block directives are not supported "
                                   "in -g option");
                goto failed;
            }
        }

        /* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */

        /* 自定义指令处理函数 */
        if (cf->handler) {

            /*
             * the custom handler, i.e., that is used in the http's
             * "types { ... }" directive
             */

            if (rc == NGX_CONF_BLOCK_START) {
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"{\"");
                goto failed;
            }

            /* 命令行配置处理函数 */
            rv = (*cf->handler)(cf, NULL, cf->handler_conf);
            if (rv == NGX_CONF_OK) {
                continue;
            }

            if (rv == NGX_CONF_ERROR) {
                goto failed;
            }

            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv);

            goto failed;
        }


        /* 若自定义指令处理函数handler为NULL,则调用Nginx内建的指令解析机制 */
        rc = ngx_conf_handler(cf, rc);

        if (rc == NGX_ERROR) {
            goto failed;
        }
    }

failed:

    rc = NGX_ERROR;

done:

    if (filename) {/* 若是配置文件 */
        if (cf->conf_file->buffer->start) {
            ngx_free(cf->conf_file->buffer->start);
        }

        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
                          ngx_close_file_n " %s failed",
                          filename->data);
            return NGX_CONF_ERROR;
        }

        cf->conf_file = prev;
    }

    if (rc == NGX_ERROR) {
        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;
}
Nach dem Login kopieren
ngx_command_t
        /* 自定义指令处理函数 */
        if (cf->handler) {

            /*
             * the custom handler, i.e., that is used in the http's
             * "types { ... }" directive
             */

            if (rc == NGX_CONF_BLOCK_START) {
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"{\"");
                goto failed;
            }

            /* 命令行配置处理函数 */
            rv = (*cf->handler)(cf, NULL, cf->handler_conf);
            if (rv == NGX_CONF_OK) {
                continue;
            }

            if (rv == NGX_CONF_ERROR) {
                goto failed;
            }

            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv);

            goto failed;
        }
Nach dem Login kopieren
, wir haben diese Struktur im Artikel „Nginx Modulentwicklung“ eingeführt und ihre Definition lautet wie folgt:
struct ngx_command_s {  
    /* 配置项名称 */  
    ngx_str_t             name;  
    /* 配置项类型,type将指定配置项可以出现的位置以及携带参数的个数 */  
    ngx_uint_t            type;  
    /* 处理配置项的参数 */  
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);  
    /* 在配置文件中的偏移量,conf与offset配合使用 */  
    ngx_uint_t            conf;  
    ngx_uint_t            offset;  
    /* 配置项读取后的处理方法,必须指向ngx_conf_post_t 结构 */  
    void                 *post;  
}; 
Nach dem Login kopieren

        若在上面的通用配置解析中,定义了如下的 http 配置项结构,则回调用http 配置项,并对该http 配置项进行解析。此时,解析的是http block 块设置。

static ngx_command_t  ngx_http_commands[] = {

    { ngx_string("http"),
      NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
      ngx_http_block,
      0,
      0,
      NULL },

      ngx_null_command
};
Nach dem Login kopieren

        http 是作为一个 core 模块被 nginx 通用解析过程解析的,其核心就是http{} 块指令回调,它完成了http 解析的整个功能,从初始化到计算配置结果。http{} 块指令的流程是:

  • 创建并初始化上下文结构;
  • 调用通用模块配置解析流程解析;
  • 根据解析结果进行配置项合并处理;

创建并初始化上下文结构

  当 Nginx 检查到 http{…} 配置项时,HTTP 配置模型就会启动,则会建立一个ngx_http_conf_ctx_t 结构,该结构定义在文件中:src/http/ngx_http_config.h

typedef struct{
  /*  指针数组,数组中的每个元素指向所有 HTTP 模块 create_main_conf 方法产生的结构体 */
   void **main_conf;
   /*  指针数组,数组中的每个元素指向所有 HTTP 模块 create_srv_conf 方法产生的结构体 */
   void **srv_conf;
   /*  指针数组,数组中的每个元素指向所有 HTTP 模块 create_loc_conf 方法产生的结构体 */
   void **loc_conf;
}ngx_http_conf_ctx_t;
Nach dem Login kopieren

  此时,HTTP 框架为所有 HTTP 模块建立 3 个数组,分别存放所有 HTTP 模块的create_main_confcreate_srv_confcreate_loc_conf 方法返回的地址指针。ngx_http_conf_ctx_t 结构的三个成员分别指向这 3 个数组。例如下面的例子是设置 create_main_confcreate_srv_conf 、create_loc_conf  返回的地址。

ngx_http_conf_ctx *ctx;
/* HTTP 框架生成 1 个 ngx_http_conf_ctx_t 结构变量 */
ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));

*(ngx_http_conf_ctx_t **) conf = ctx;

...
/* 分别生成 3 个数组存储所有的 HTTP 模块的 create_main_conf、create_srv_conf、create_loc_conf 方法返回的地址 */
ctx->main_conf = ngx_pcalloc(cf->pool,
                             sizeof(void *) * ngx_http_max_module);

ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);

ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);

/* 遍历所有 HTTP 模块 */
for (m = 0; ngx_modules[m]; m++) {
    if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
        continue;
    }

    module = ngx_modules[m]->ctx;
    mi = ngx_modules[m]->ctx_index;

    /* 若实现了create_main_conf 方法,则调用该方法,并把返回的地址存储到 main_conf 中 */
    if (module->create_main_conf) {
        ctx->main_conf[mi] = module->create_main_conf(cf);
    }
    /* 若实现了create_srv_conf 方法,则调用该方法,并把返回的地址存储到 srv_conf 中 */
    if (module->create_srv_conf) {
        ctx->srv_conf[mi] = module->create_srv_conf(cf);
    }
    /* 若实现了create_loc_conf 方法,则调用该方法,并把返回的地址存储到 loc_conf 中 */
    if (module->create_loc_conf) {
        ctx->loc_conf[mi] = module->create_loc_conf(cf);
    }
}

pcf = *cf;
cf->ctx = ctx;

for (m = 0; ngx_modules[m]; m++) {
    if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
        continue;
    }

    module = ngx_modules[m]->ctx;

    if (module->preconfiguration) {
        if (module->preconfiguration(cf) != NGX_OK) {
            return NGX_CONF_ERROR;
        }
    }
}
Nach dem Login kopieren

调用通用模块配置解析流程解析

        从源码 src/http/ngx_http.c 中可以看到,http 块的配置解析是调用通用模块的配置解析函数,其实现如下:

    /* 调用通用模块配置解析 */
    /* parse inside the http{} block */

    cf->module_type = NGX_HTTP_MODULE;
    cf->cmd_type = NGX_HTTP_MAIN_CONF;
    rv = ngx_conf_parse(cf, NULL);

    if (rv != NGX_CONF_OK) {
        goto failed;
    }
Nach dem Login kopieren

根据解析结果进行配置项合并处理

    /* 根据解析结构进行合并处理 */
    /*
     * init http{} main_conf's, merge the server{}s' srv_conf's
     * and its location{}s' loc_conf's
     */

    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
    cscfp = cmcf->servers.elts;

    for (m = 0; ngx_modules[m]; m++) {
        if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = ngx_modules[m]->ctx;
        mi = ngx_modules[m]->ctx_index;

        /* init http{} main_conf's */

        if (module->init_main_conf) {
            rv = module->init_main_conf(cf, ctx->main_conf[mi]);
            if (rv != NGX_CONF_OK) {
                goto failed;
            }
        }

        rv = ngx_http_merge_servers(cf, cmcf, module, mi);
        if (rv != NGX_CONF_OK) {
            goto failed;
        }
    }


    /* create location trees */

    for (s = 0; s < cmcf->servers.nelts; s++) {

        clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];

        if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
            return NGX_CONF_ERROR;
        }

        if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
            return NGX_CONF_ERROR;
        }
    }


    if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }


    for (m = 0; ngx_modules[m]; m++) {
        if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
            continue;
        }

        module = ngx_modules[m]->ctx;

        if (module->postconfiguration) {
            if (module->postconfiguration(cf) != NGX_OK) {
                return NGX_CONF_ERROR;
            }
        }
    }

    if (ngx_http_variables_init_vars(cf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    /*
     * http{}'s cf->ctx was needed while the configuration merging
     * and in postconfiguration process
     */

    *cf = pcf;


    if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
        return NGX_CONF_ERROR;
    }


    /* optimize the lists of ports, addresses and server names */

    if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;

failed:

    *cf = pcf;

    return rv;
Nach dem Login kopieren

HTTP 配置解析流程

        从上面的分析中可以总结出 HTTP 配置解析的流程如下:

  • Nginx 进程进入主循环,在主循环中调用配置解析器解析配置文件nginx.conf;
  • 在配置文件中遇到 http{} 块配置,则 HTTP 框架开始启动,其由函数 ngx_http_block() 实现;
  • HTTP 框架初始化所有 HTTP 模块的序列号,并创建 3 个类型为 ngx_http_conf_ctx_t 结构的数组用于存储所有HTTP 模块的create_main_confcreate_srv_confcreate_loc_conf方法返回的指针地址;
  • 调用每个 HTTP 模块的 preconfiguration 方法;
  • HTTP 框架调用函数 ngx_conf_parse() 开始循环解析配置文件 nginx.conf 中的http{}块里面的所有配置项;
  • HTTP 框架处理完毕 http{} 配置项,根据解析配置项的结果,必要时进行配置项合并处理;
  • 继续处理其他 http{} 块之外的配置项,直到配置文件解析器处理完所有配置项后通知Nginx 主循环配置项解析完毕。此时,Nginx 才会启动Web 服务器;

合并配置项

        HTTP 框架解析完毕 http{} 块配置项时,会根据解析的结果进行合并配置项操作,即合并 http{}server{}location{} 不同块下各HTTP 模块生成的存放配置项的结构体。其合并过程如下所示:

  • HTTP 模块实现了 merge_srv_conf 方法,则将 http{} 块下create_srv_conf 生成的结构体与遍历每一个 server{}配置块下的结构体进行merge_srv_conf 操作;
  • HTTP 模块实现了 merge_loc_conf 方法,则将 http{} 块下create_loc_conf 生成的结构体与嵌套每一个server{} 配置块下的结构体进行merge_loc_conf 操作;
  • HTTP 模块实现了 merge_loc_conf 方法,则将server{} 块下create_loc_conf 生成的结构体与嵌套每一个location{}配置块下的结构体进行merge_loc_conf 操作;
  • HTTP 模块实现了 merge_loc_conf 方法,则将location{} 块下create_loc_conf 生成的结构体与嵌套每一个location{}配置块下的结构体进行merge_loc_conf 操作;

        以下是合并配置项操作的源码实现:

/* 合并配置项操作 */
static char *
ngx_http_merge_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
    ngx_http_module_t *module, ngx_uint_t ctx_index)
{
    char                        *rv;
    ngx_uint_t                   s;
    ngx_http_conf_ctx_t         *ctx, saved;
    ngx_http_core_loc_conf_t    *clcf;
    ngx_http_core_srv_conf_t   **cscfp;

    cscfp = cmcf->servers.elts;
    ctx = (ngx_http_conf_ctx_t *) cf->ctx;
    saved = *ctx;
    rv = NGX_CONF_OK;

    /* 遍历每一个server{}块 */
    for (s = 0; s < cmcf->servers.nelts; s++) {

        /* merge the server{}s' srv_conf's */

        ctx->srv_conf = cscfp[s]->ctx->srv_conf;

        /*
         * 若定义了merge_srv_conf 方法;
         * 则进行http{}块下create_srv_conf 生成的结构体与遍历server{}块配置项生成的结构体进行merge_srv_conf操作;
         */
        if (module->merge_srv_conf) {
            rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index],
                                        cscfp[s]->ctx->srv_conf[ctx_index]);
            if (rv != NGX_CONF_OK) {
                goto failed;
            }
        }

        /*
         * 若定义了merge_loc_conf 方法;
         * 则进行http{}块下create_loc_conf 生成的结构体与嵌套server{}块配置项生成的结构体进行merge_loc_conf操作;
         */
        if (module->merge_loc_conf) {

            /* merge the server{}'s loc_conf */

            ctx->loc_conf = cscfp[s]->ctx->loc_conf;

            rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index],
                                        cscfp[s]->ctx->loc_conf[ctx_index]);
            if (rv != NGX_CONF_OK) {
                goto failed;
            }

            /* merge the locations{}' loc_conf's */

            /*
             * 若定义了merge_loc_conf 方法;
             * 则进行server{}块下create_loc_conf 生成的结构体与嵌套location{}块配置项生成的结构体进行merge_loc_conf操作;
             */
            clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];

            rv = ngx_http_merge_locations(cf, clcf->locations,
                                          cscfp[s]->ctx->loc_conf,
                                          module, ctx_index);
            if (rv != NGX_CONF_OK) {
                goto failed;
            }
        }
    }

failed:

    *ctx = saved;

    return rv;
}


static char *
ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
    void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
{
    char                       *rv;
    ngx_queue_t                *q;
    ngx_http_conf_ctx_t        *ctx, saved;
    ngx_http_core_loc_conf_t   *clcf;
    ngx_http_location_queue_t  *lq;

    if (locations == NULL) {
        return NGX_CONF_OK;
    }

    ctx = (ngx_http_conf_ctx_t *) cf->ctx;
    saved = *ctx;

    /*
     * 若定义了merge_loc_conf 方法;
     * 则进行location{}块下create_loc_conf 生成的结构体与嵌套location{}块配置项生成的结构体进行merge_loc_conf操作;
     */
    for (q = ngx_queue_head(locations);
         q != ngx_queue_sentinel(locations);
         q = ngx_queue_next(q))
    {
        lq = (ngx_http_location_queue_t *) q;

        clcf = lq->exact ? lq->exact : lq->inclusive;
        ctx->loc_conf = clcf->loc_conf;

        rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
                                    clcf->loc_conf[ctx_index]);
        if (rv != NGX_CONF_OK) {
            return rv;
        }

        /*
         * 递归调用该函数;
         * 因为location{}继续内嵌location{}
         */
        rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
                                      module, ctx_index);
        if (rv != NGX_CONF_OK) {
            return rv;
        }
    }

    *ctx = saved;

    return NGX_CONF_OK;
}

Nach dem Login kopieren

处理自定义的配置

        在文章中 《Nginx 模块开发》,我们给出了“Hello World” 的开发例子,在这个开发例子中,我们定义了自己的配置项,配置项名称的结构体定义如下:

typedef struct  
{  
        ngx_str_t hello_string;  
        ngx_int_t hello_counter;  
}ngx_http_hello_loc_conf_t;  
Nach dem Login kopieren

        为了处理我们定义的配置项结构,因此,我们把 ngx_command_t 结构体定义如下:

static ngx_command_t ngx_http_hello_commands[] = {  
   {  
                ngx_string("hello_string"),  
                NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,  
                ngx_http_hello_string,  
                NGX_HTTP_LOC_CONF_OFFSET,  
                offsetof(ngx_http_hello_loc_conf_t, hello_string),  
                NULL },  
  
        {  
                ngx_string("hello_counter"),  
                NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,  
                ngx_http_hello_counter,  
                NGX_HTTP_LOC_CONF_OFFSET,  
                offsetof(ngx_http_hello_loc_conf_t, hello_counter),  
                NULL },  
  
        ngx_null_command  
};  
Nach dem Login kopieren

        处理方法 ngx_http_hello_stringngx_http_hello_counter 定义如下:

static char *  
ngx_http_hello_string(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)  
{  
  
        ngx_http_hello_loc_conf_t* local_conf;  
  
  
        local_conf = conf;  
        char* rv = ngx_conf_set_str_slot(cf, cmd, conf);  
  
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "hello_string:%s", local_conf->hello_string.data);  
  
        return rv;  
}  
  
  
static char *ngx_http_hello_counter(ngx_conf_t *cf, ngx_command_t *cmd,  
        void *conf)  
{  
        ngx_http_hello_loc_conf_t* local_conf;  
  
        local_conf = conf;  
  
        char* rv = NULL;  
  
        rv = ngx_conf_set_flag_slot(cf, cmd, conf);  
  
  
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "hello_counter:%d", local_conf->hello_counter);  
        return rv;  
}  
Nach dem Login kopieren

参考资料:

《深入理解 Nginx 》

《nginx 启动阶段》

《Nginx高性能Web服务器详解》

以上就介绍了Nginx 配置解析,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Wie man alles in Myrise freischaltet
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Lösung: Ihre Organisation verlangt von Ihnen, dass Sie Ihre PIN ändern Lösung: Ihre Organisation verlangt von Ihnen, dass Sie Ihre PIN ändern Oct 04, 2023 pm 05:45 PM

Auf dem Anmeldebildschirm wird die Meldung „Ihre Organisation hat Sie gebeten, Ihre PIN zu ändern“ angezeigt. Dies geschieht, wenn das PIN-Ablauflimit auf einem Computer erreicht wird, der organisationsbasierte Kontoeinstellungen verwendet und die Kontrolle über persönliche Geräte hat. Wenn Sie Windows jedoch über ein persönliches Konto einrichten, sollte die Fehlermeldung im Idealfall nicht erscheinen. Obwohl dies nicht immer der Fall ist. Die meisten Benutzer, die auf Fehler stoßen, melden dies über ihre persönlichen Konten. Warum fordert mich meine Organisation auf, meine PIN unter Windows 11 zu ändern? Es ist möglich, dass Ihr Konto mit einer Organisation verknüpft ist. Ihr primärer Ansatz sollte darin bestehen, dies zu überprüfen. Die Kontaktaufnahme mit Ihrem Domain-Administrator kann hilfreich sein! Darüber hinaus können falsch konfigurierte lokale Richtlinieneinstellungen oder falsche Registrierungsschlüssel Fehler verursachen. Im Augenblick

So passen Sie die Fensterrahmeneinstellungen unter Windows 11 an: Farbe und Größe ändern So passen Sie die Fensterrahmeneinstellungen unter Windows 11 an: Farbe und Größe ändern Sep 22, 2023 am 11:37 AM

Windows 11 bringt frisches und elegantes Design in den Vordergrund; die moderne Benutzeroberfläche ermöglicht es Ihnen, feinste Details, wie zum Beispiel Fensterränder, zu personalisieren und zu ändern. In diesem Leitfaden besprechen wir Schritt-für-Schritt-Anleitungen, die Ihnen dabei helfen, eine Umgebung zu erstellen, die Ihrem Stil im Windows-Betriebssystem entspricht. Wie ändere ich die Fensterrahmeneinstellungen? Drücken Sie +, um die Einstellungen-App zu öffnen. WindowsIch gehe zu Personalisierung und klicke auf Farbeinstellungen. Farbänderung Fensterränder Einstellungen Fenster 11" Breite="643" Höhe="500" > Suchen Sie die Option Akzentfarbe auf Titelleiste und Fensterrändern anzeigen und schalten Sie den Schalter daneben um. Um Akzentfarben im Startmenü und in der Taskleiste anzuzeigen Um die Designfarbe im Startmenü und in der Taskleiste anzuzeigen, aktivieren Sie „Design im Startmenü und in der Taskleiste anzeigen“.

Was sind die Unterschiede zwischen Huawei GT3 Pro und GT4? Was sind die Unterschiede zwischen Huawei GT3 Pro und GT4? Dec 29, 2023 pm 02:27 PM

Viele Benutzer werden sich bei der Auswahl von Smartwatches für die Marke Huawei entscheiden. Viele Benutzer sind neugierig auf den Unterschied zwischen Huawei GT3pro und GT4. Was sind die Unterschiede zwischen Huawei GT3pro und GT4? 1. Aussehen GT4: 46 mm und 41 mm, das Material ist Glasspiegel + Edelstahlgehäuse + hochauflösende Faserrückschale. GT3pro: 46,6 mm und 42,9 mm, das Material ist Saphirglas + Titangehäuse/Keramikgehäuse + Keramikrückschale 2. Gesundes GT4: Mit dem neuesten Huawei Truseen5.5+-Algorithmus werden die Ergebnisse genauer. GT3pro: EKG-Elektrokardiogramm sowie Blutgefäß und Sicherheit hinzugefügt

Anleitung zur Anzeigeskalierung unter Windows 11 Anleitung zur Anzeigeskalierung unter Windows 11 Sep 19, 2023 pm 06:45 PM

Wir alle haben unterschiedliche Vorlieben, wenn es um die Anzeigeskalierung unter Windows 11 geht. Manche Leute mögen große Symbole, andere mögen kleine Symbole. Wir sind uns jedoch alle einig, dass die richtige Skalierung wichtig ist. Eine schlechte Schriftartenskalierung oder eine Überskalierung von Bildern kann bei der Arbeit ein echter Produktivitätskiller sein. Sie müssen daher wissen, wie Sie sie anpassen können, um die Fähigkeiten Ihres Systems optimal zu nutzen. Vorteile des benutzerdefinierten Zooms: Dies ist eine nützliche Funktion für Personen, die Schwierigkeiten haben, Text auf dem Bildschirm zu lesen. Es hilft Ihnen, mehr gleichzeitig auf dem Bildschirm zu sehen. Sie können benutzerdefinierte Erweiterungsprofile erstellen, die nur für bestimmte Monitore und Anwendungen gelten. Kann dazu beitragen, die Leistung von Low-End-Hardware zu verbessern. Dadurch haben Sie mehr Kontrolle darüber, was auf Ihrem Bildschirm angezeigt wird. So verwenden Sie Windows 11

10 Möglichkeiten, die Helligkeit unter Windows 11 anzupassen 10 Möglichkeiten, die Helligkeit unter Windows 11 anzupassen Dec 18, 2023 pm 02:21 PM

Die Bildschirmhelligkeit ist ein wesentlicher Bestandteil der Nutzung moderner Computergeräte, insbesondere wenn Sie über einen längeren Zeitraum auf den Bildschirm schauen. Es hilft Ihnen, die Belastung Ihrer Augen zu reduzieren, die Lesbarkeit zu verbessern und Inhalte einfach und effizient anzuzeigen. Abhängig von Ihren Einstellungen kann es jedoch manchmal schwierig sein, die Helligkeit zu verwalten, insbesondere unter Windows 11 mit den neuen Änderungen an der Benutzeroberfläche. Wenn Sie Probleme beim Anpassen der Helligkeit haben, finden Sie hier alle Möglichkeiten, die Helligkeit unter Windows 11 zu verwalten. So ändern Sie die Helligkeit unter Windows 11 [10 Möglichkeiten erklärt] Benutzer eines einzelnen Monitors können die folgenden Methoden verwenden, um die Helligkeit unter Windows 11 anzupassen. Hierzu zählen sowohl Desktop-Systeme mit einem einzelnen Monitor als auch Laptops. Lasst uns beginnen. Methode 1: Verwenden Sie das Action Center. Das Action Center ist zugänglich

Wie deaktiviere ich die Authentifizierung beim privaten Surfen auf dem iPhone in Safari? Wie deaktiviere ich die Authentifizierung beim privaten Surfen auf dem iPhone in Safari? Nov 29, 2023 pm 11:21 PM

Mit iOS 17 hat Apple mehrere neue Datenschutz- und Sicherheitsfunktionen in sein mobiles Betriebssystem eingeführt, darunter die Möglichkeit, eine zweistufige Authentifizierung für private Browser-Tabs in Safari zu verlangen. Hier erfahren Sie, wie es funktioniert und wie Sie es ausschalten. Auf einem iPhone oder iPad mit iOS 17 oder iPadOS 17 erfordert der Browser von Apple jetzt eine Face ID/Touch ID-Authentifizierung oder einen Passcode, wenn Sie in Safari eine Registerkarte „Privates Surfen“ geöffnet haben und dann die Sitzung oder App verlassen, um erneut darauf zuzugreifen. Mit anderen Worten: Wenn jemand Ihr iPhone oder iPad in die Hände bekommt, während es entsperrt ist, kann er Ihre Privatsphäre trotzdem nicht einsehen, ohne Ihren Passcode zu kennen

Was bedeutet der http-Statuscode 520? Was bedeutet der http-Statuscode 520? Oct 13, 2023 pm 03:11 PM

Der HTTP-Statuscode 520 bedeutet, dass der Server bei der Verarbeitung der Anfrage einen unbekannten Fehler festgestellt hat und keine genaueren Informationen bereitstellen kann. Wird verwendet, um darauf hinzuweisen, dass bei der Verarbeitung der Anforderung durch den Server ein unbekannter Fehler aufgetreten ist, der durch Serverkonfigurationsprobleme, Netzwerkprobleme oder andere unbekannte Gründe verursacht werden kann. Dies wird normalerweise durch Serverkonfigurationsprobleme, Netzwerkprobleme, Serverüberlastung oder Codierungsfehler verursacht. Wenn Sie auf einen Fehler mit dem Statuscode 520 stoßen, wenden Sie sich am besten an den Website-Administrator oder das technische Support-Team, um weitere Informationen und Unterstützung zu erhalten.

Das digitale Aktivierungsskript für Win10/11 MAS Version 2.2 unterstützt erneut die digitale Aktivierung Das digitale Aktivierungsskript für Win10/11 MAS Version 2.2 unterstützt erneut die digitale Aktivierung Oct 16, 2023 am 08:13 AM

Das berühmte Aktivierungsskript MAS2.2 unterstützt wieder die digitale Aktivierung. Die Methode stammt von @asdcorp und der MAS-Autor nennt sie HWID2. Laden Sie „gatherosstate.exe“ (kein Original, geändert) von https://github.com/massgravel/Microsoft-Activation-Scripts herunter, führen Sie es mit Parametern aus und generieren Sie GenuineTicket.xml. Schauen Sie sich zunächst die ursprüngliche Methode an: Gatherosstate.exePfn=xxxxxxx;DownlevelGenuineState=1 und vergleichen Sie sie dann mit der neuesten Methode: Gatheros

See all articles