目次
ブロック、および location ブロックが含まれます。
ブロック、location ブロックの 3 つのスコープに同時に存在する可能性があります。

Nginx構成分析

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

概要

前回の記事では『 Nginx の起動初期化プロセス」では、Nginx の起動プロセスを簡単に紹介し、その起動プロセスのソース コードを分析します。起動プロセスには、関数 ngx_init_cycle() を呼び出すという非常に重要なステップがあります。この関数の呼び出しにより、構成分析用のインターフェイスが提供されます。構成分析インターフェイスは、データの準備段階と構成分析段階の 2 つの段階に分けることができます。解析段階では、次の関数を呼び出します。設定ファイルを解析する際の各ディレクティブの属性。これは、

Nginx

プログラム内で非常に重要なデータ構造です。

src/core/ngx_conf_file.h
    /* 配置文件解析 */  
    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;  
    }  
ログイン後にコピー
  • 設定ファイル。情報
  • conf_file
  • conf_file

    は、

    Nginx

    設定ファイルの関連情報を保存します。

    ngx_conf_file_t 構造の定義は次のとおりです:

    /* 解析配置时所使用的结构体 */
    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;/* 自定义处理函数需要的相关配置 */
    };
    
    ログイン後にコピー
    構成コンテキスト

    ctx Nginx 構成ファイルはブロックで構成されます。一般的なものには、http
    ブロック、

    server

    ブロック、および location ブロックが含まれます。

    アップストリーム

    ブロックやメールブロックなど。このような各構成ブロックはスコープを表します。上位レベルの構成ブロックのスコープには、複数の下位レベルの構成ブロックのスコープが含まれます。これは、スコープのネスト現象です。このようにして、構成ファイル内の多くのディレクティブが同時に複数のスコープに含まれるようになります。たとえば、http ブロック内の命令は、http ブロック、

    server

    ブロック、location ブロックの 3 つのスコープに同時に存在する可能性があります。

    Nginx プログラムが構成ファイルを解析するとき、各命令はそれが属するスコープを記録する必要があり、構成ファイルのコンテキスト ctx 変数は現在の命令が属するスコープを保存するために使用されます。 Nginx 構成ファイルのさまざまな構成ブロックのうち、http ブロックには、ストレージ構造の点でより複雑なサブ構成ブロックを含めることができます。 命令 pType の異なる命令タイプ Nginx プログラムは、マクロの形式で異なるソース dock ファイルで定義されます。 これらは、core タイプのモジュールによってサポートされる命令タイプです。 NGX_DIRECT_CONF クラス命令は、Nginx プログラムが設定解析関数に入る前に初期化されているため、設定解析関数に入った後、設定ファイルの構造から直接解析して実際のデータ構造に保存できます。これらは通常、構成ブロックの外側にあり、構成ファイルのグローバル ブロック部分にある命令を指します。

    NGX_MAIN_CONF

    クラスの命令には、eventhttpmailupstream およびその他の構成ブロックを形成できる命令が含まれます。これらには独自の初期化関数がありません。

    Nginx

    プログラムが構成ファイルを解析するときに NGX_MAIN_CONF クラス命令に遭遇すると、次のレベルの命令の解析に移行します。

    以下は、

    eventタイプのモジュールによってサポートされる命令タイプです。

    typedef struct {
        ngx_file_t            file;     /* 文件的属性 */
        ngx_buf_t            *buffer;   /* 文件的内容 */
        ngx_uint_t            line;     /* 文件的行数 */
    } ngx_conf_file_t;
    ログイン後にコピー
    以下は、http タイプのモジュールでサポートされている命令タイプであり、ファイルで定義されています: src/http/ngx_http_config.h
    #define NGX_DIRECT_CONF            0x00010000  
    #define NGX_MAIN_CONF              0x01000000  
    #define NGX_ANY_CONF               0x0F000000 
    ログイン後にコピー
    一般的なモジュール構成解析 構成解析モジュールは次のとおりです。 src/core/ngx_conf_file.cに実装されています。モジュールが提供するインターフェース関数は主に ngx_conf_parse です。さらに、このモジュールは、コマンドラインから渡された設定を解析するために使用される別のインターフェース ngx_conf_param を提供します。このインターフェースは ngx_conf_parse のラッパーでもあります。まず、次のように定義されている構成解析関数 ngx_conf_parse を見てみましょう:
    #define NGX_EVENT_CONF            0x02000000 
    ログイン後にコピー
    構成解析関数のソース コードから、この関数が構文解析と命令解析の 2 つの段階に分かれていることがわかります。 。構文分析は、
    ngx_conf_read_token() 関数によって完了します。コマンド解析には 2 つの方法があります。1 つは Nginx の組み込みコマンド解析メカニズムで、もう 1 つはカスタム コマンド解析メカニズムです。カスタム命令解析のソース コードは次のとおりです。
    #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  
    ログイン後にコピー
    そして、
    Nginx

    の組み込み解析メカニズムは、関数ngx_conf_handler()によって実装されます。その定義は次のとおりです:

    /*
     * 函数功能:配置文件解析;
     * 支持三种不同的解析类型:
     * 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;
    }
    
    ログイン後にコピー

    HTTP モジュール構成解析 ここでの主な構造は

    ngx_command_t

    です。この構造は「Nginxモジュール開発」の記事で紹介しましたが、その定義は次のとおりです。 :

    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;  
    }; 
    
    ログイン後にコピー

            若在上面的通用配置解析中,定义了如下的 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
    };
    
    ログイン後にコピー

            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;
    
    ログイン後にコピー

      此时,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;
            }
        }
    }
    
    ログイン後にコピー

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

            从源码 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;
        }
    
    ログイン後にコピー

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

        /* 根据解析结构进行合并处理 */
        /*
         * 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;
    
    ログイン後にコピー

    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;
    }
    
    
    ログイン後にコピー

    处理自定义的配置

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

    typedef struct  
    {  
            ngx_str_t hello_string;  
            ngx_int_t hello_counter;  
    }ngx_http_hello_loc_conf_t;  
    
    ログイン後にコピー

            为了处理我们定义的配置项结构,因此,我们把 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  
    };  
    
    ログイン後にコピー

            处理方法 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;  
    }  
    
    ログイン後にコピー

    参考资料:

    《深入理解 Nginx 》

    《nginx 启动阶段》

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

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

  • このウェブサイトの声明
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

    ホットAIツール

    Undresser.AI Undress

    Undresser.AI Undress

    リアルなヌード写真を作成する AI 搭載アプリ

    AI Clothes Remover

    AI Clothes Remover

    写真から衣服を削除するオンライン AI ツール。

    Undress AI Tool

    Undress AI Tool

    脱衣画像を無料で

    Clothoff.io

    Clothoff.io

    AI衣類リムーバー

    AI Hentai Generator

    AI Hentai Generator

    AIヘンタイを無料で生成します。

    ホットツール

    メモ帳++7.3.1

    メモ帳++7.3.1

    使いやすく無料のコードエディター

    SublimeText3 中国語版

    SublimeText3 中国語版

    中国語版、とても使いやすい

    ゼンドスタジオ 13.0.1

    ゼンドスタジオ 13.0.1

    強力な PHP 統合開発環境

    ドリームウィーバー CS6

    ドリームウィーバー CS6

    ビジュアル Web 開発ツール

    SublimeText3 Mac版

    SublimeText3 Mac版

    神レベルのコード編集ソフト(SublimeText3)

    解決策: 組織では PIN を変更する必要があります。 解決策: 組織では PIN を変更する必要があります。 Oct 04, 2023 pm 05:45 PM

    ログイン画面に「組織から PIN の変更を求められています」というメッセージが表示されます。これは、個人のデバイスを制御できる組織ベースのアカウント設定を使用しているコンピューターで PIN の有効期限の制限に達した場合に発生します。ただし、個人アカウントを使用して Windows をセットアップした場合、エラー メッセージは表示されないのが理想的です。常にそうとは限りませんが。エラーが発生したほとんどのユーザーは、個人アカウントを使用して報告します。私の組織が Windows 11 で PIN を変更するように要求するのはなぜですか?アカウントが組織に関連付けられている可能性があるため、主なアプローチはこれを確認することです。ドメイン管理者に問い合わせると解決できます。さらに、ローカル ポリシー設定が間違っていたり、レジストリ キーが間違っていたりすると、エラーが発生する可能性があります。今すぐ

    Windows 11 でウィンドウの境界線の設定を調整する方法: 色とサイズを変更する Windows 11 でウィンドウの境界線の設定を調整する方法: 色とサイズを変更する Sep 22, 2023 am 11:37 AM

    Windows 11 では、新鮮でエレガントなデザインが前面に押し出されており、最新のインターフェイスにより、ウィンドウの境界線などの細部をカスタマイズして変更することができます。このガイドでは、Windows オペレーティング システムで自分のスタイルを反映した環境を作成するのに役立つ手順について説明します。ウィンドウの境界線の設定を変更するにはどうすればよいですか? + を押して設定アプリを開きます。 Windows [個人用設定] に移動し、[色の設定] をクリックします。ウィンドウの境界線の色の変更設定ウィンドウ 11" width="643" height="500" > [タイトル バーとウィンドウの境界線にアクセント カラーを表示する] オプションを見つけて、その横にあるスイッチを切り替えます。 [スタート] メニューとタスク バーにアクセント カラーを表示するにはスタート メニューとタスク バーにテーマの色を表示するには、[スタート メニューとタスク バーにテーマを表示] をオンにします。

    Windows 11 でのディスプレイ スケーリング ガイド Windows 11 でのディスプレイ スケーリング ガイド Sep 19, 2023 pm 06:45 PM

    Windows 11 のディスプレイ スケーリングに関しては、好みが人それぞれ異なります。大きなアイコンを好む人もいれば、小さなアイコンを好む人もいます。ただし、適切なスケーリングが重要であることには誰もが同意します。フォントのスケーリングが不十分であったり、画像が過度にスケーリングされたりすると、作業中の生産性が大幅に低下する可能性があるため、システムの機能を最大限に活用するためにカスタマイズする方法を知る必要があります。カスタム ズームの利点: これは、画面上のテキストを読むのが難しい人にとって便利な機能です。一度に画面上でより多くの情報を確認できるようになります。特定のモニターおよびアプリケーションにのみ適用するカスタム拡張プロファイルを作成できます。ローエンド ハードウェアのパフォーマンスの向上に役立ちます。画面上の内容をより詳細に制御できるようになります。 Windows 11の使用方法

    Huawei GT3 ProとGT4の違いは何ですか? Huawei GT3 ProとGT4の違いは何ですか? Dec 29, 2023 pm 02:27 PM

    多くのユーザーはスマートウォッチを選ぶときにファーウェイブランドを選択しますが、その中でもファーウェイ GT3pro と GT4 は非常に人気のある選択肢であり、多くのユーザーはファーウェイ GT3pro と GT4 の違いに興味を持っています。 Huawei GT3pro と GT4 の違いは何ですか? 1. 外観 GT4: 46mm と 41mm、材質はガラスミラー + ステンレススチールボディ + 高解像度ファイバーバックシェルです。 GT3pro: 46.6mm および 42.9mm、材質はサファイアガラス + チタンボディ/セラミックボディ + セラミックバックシェルです。 2. 健全な GT4: 最新の Huawei Truseen5.5+ アルゴリズムを使用すると、結果はより正確になります。 GT3pro: ECG 心電図と血管と安全性を追加

    Windows 11で明るさを調整する10の方法 Windows 11で明るさを調整する10の方法 Dec 18, 2023 pm 02:21 PM

    画面の明るさは、最新のコンピューティング デバイスを使用する上で不可欠な部分であり、特に長時間画面を見る場合には重要です。目の疲れを軽減し、可読性を向上させ、コンテンツを簡単かつ効率的に表示するのに役立ちます。ただし、設定によっては、特に新しい UI が変更された Windows 11 では、明るさの管理が難しい場合があります。明るさの調整に問題がある場合は、Windows 11 で明るさを管理するすべての方法を次に示します。 Windows 11で明るさを変更する方法【10の方法を解説】 シングルモニターユーザーは、次の方法でWindows 11の明るさを調整できます。これには、ラップトップだけでなく、単一のモニターを使用するデスクトップ システムも含まれます。はじめましょう。方法 1: アクション センターを使用する アクション センターにアクセスできる

    http ステータス コード 520 は何を意味しますか? http ステータス コード 520 は何を意味しますか? Oct 13, 2023 pm 03:11 PM

    HTTP ステータス コード 520 は、サーバーがリクエストの処理中に不明なエラーに遭遇し、より具体的な情報を提供できないことを意味します。サーバーがリクエストを処理しているときに不明なエラーが発生したことを示すために使用されます。サーバー構成の問題、ネットワークの問題、またはその他の不明な理由が原因である可能性があります。これは通常、サーバー構成の問題、ネットワークの問題、サーバーの過負荷、またはコーディング エラーが原因で発生します。ステータス コード 520 エラーが発生した場合は、Web サイト管理者またはテクニカル サポート チームに連絡して詳細情報と支援を得ることが最善です。

    iPhoneのSafariでプライベートブラウジング認証をオフにする方法は? iPhoneのSafariでプライベートブラウジング認証をオフにする方法は? Nov 29, 2023 pm 11:21 PM

    iOS 17 では、Apple はモバイル オペレーティング システムにいくつかの新しいプライバシーおよびセキュリティ機能を導入しました。その 1 つは、Safari のプライベート ブラウジング タブに対して 2 段階認証を要求する機能です。その仕組みとオフにする方法は次のとおりです。 iOS 17 または iPadOS 17 を実行している iPhone または iPad では、Safari でプライベート ブラウズ タブを開いていて、再度アクセスするためにセッションまたはアプリを終了する場合、Apple のブラウザでは Face ID/Touch ID 認証またはパスコードが必要になります。言い換えれば、ロックが解除されている iPhone または iPad を誰かが手に入れても、パスコードを知らなければプライバシーを閲覧することはできません。

    Win10/11 デジタル アクティベーション スクリプト MAS バージョン 2.2 がデジタル アクティベーションを再サポート Win10/11 デジタル アクティベーション スクリプト MAS バージョン 2.2 がデジタル アクティベーションを再サポート Oct 16, 2023 am 08:13 AM

    有名なアクティベーション スクリプト MAS2.2 バージョンでは、デジタル アクティベーションが再びサポートされています。このメソッドは @asdcorp とそのチームが考案したもので、MAS 作成者はそれを HWID2 と呼んでいます。 https://github.com/massgravel/Microsoft-Activation-Scripts から Gatherosstate.exe (オリジナルではなく、変更されたもの) をダウンロードし、パラメータを指定して実行し、AuthenticTicket.xml を生成します。まず元のメソッド: Gatherosstate.exePfn=xxxxxxx;DownlevelOriginalState=1 を確認し、次に最新のメソッド: Gatheros と比較します。

    See all articles