《深入剖析ngx》——请求定位

1. location 指令 配置解析

1.1 指令格式

location配置支持如下格式,
location 的参数是 uri, 可以是模糊的,也可以是绝对的

1.2 配置解析——生成loc树

  2949 static char *
  2950 ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
  2951 {
          // 创建 loc 配置块
  2976     for (i = 0; cf->cycle->modules[i]; i++) {
  2977         if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {
  2978             continue;
  2979         }
  2980
  2981         module = cf->cycle->modules[i]->ctx;
  2982
  2983         if (module->create_loc_conf) {
  2984             ctx->loc_conf[cf->cycle->modules[i]->ctx_index] =
  2985                                                    module->create_loc_conf(c       f);
  2986             if (ctx->loc_conf[cf->cycle->modules[i]->ctx_index] == NULL) {
  2987                 return NGX_CONF_ERROR;
  2988             }
  2989         }
  2990     }
  2992     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
  2993     clcf->loc_conf = ctx->loc_conf;
          。。。
          // 将 clcf 加入 locations 队列
  3127     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
  3128         return NGX_CONF_ERROR;
  3129     }
  3130     // 切换配置上下文,解析 location {} 内配置
  3131     save = *cf;
  3132     cf->ctx = ctx;
  3133     cf->cmd_type = NGX_HTTP_LOC_CONF;
  3134
  3135     rv = ngx_conf_parse(cf, NULL);

以上 location 为 命名loc,
另外还有 未命名loc,即 使用 if, limit_except 指令 配置生成的location, 其 clcf->noname=1,这些loc会加入loc树,构成如下结构

同级的loc为一个节点,loc嵌套为子树

1.3 配置解析——优化loc树

为了提高效率,ngx对loc树进行合并裁剪

loc树裁剪前

裁剪后

数据结构

2. server定位

所谓server定位,就是找到 报文目的主机 相关的 配置上下文。

ngx 接受到TCP连接时,先从套接字获得目的地址,

ngx 支持虚拟主机,判断 报文的目的主机是哪台 虚拟主机时,必须分析 请求头,
但在解析 请求 前,必须设置 服务器配置上下文,
所以 ngx 使用 default server 作为预先配置

   206 void
   207 ngx_http_init_connection(ngx_connection_t *c)
   208 {
   234     if (port->naddrs > 1) {
   235
   241          // 获得目的地址
   242         if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
   243             ngx_http_close_connection(c);
   244             return;
   245         }
               // 根据
   268         default: /* AF_INET */
   269             sin = (struct sockaddr_in *) c->local_sockaddr;
   270
   271             addr = port->addrs;
   272
   273             /* the last address is "*" */
   274
   275             for (i = 0; i < port->naddrs - 1; i++) {
   276                 if (addr[i].addr == sin->sin_addr.s_addr) {
   277                     break;
   278                 }
   279             }
   281             hc->addr_conf = &addr[i].conf;
   282
   283             break;
   284         }
           // 使用默认主机配置
   304     /* the default server configuration for the address:port */
   305     hc->conf_ctx = hc->addr_conf->default_server->ctx;
           // 下一个事件处理为 ngx_http_wait_request_handler
   325     rev->handler = ngx_http_wait_request_handler;

      
   377 static void
   378 ngx_http_wait_request_handler(ngx_event_t *rev)
   379 {
          // 构造报文
   496     c->data = ngx_http_create_request(c);
            // 解析报文
   503     ngx_http_process_request_line(rev);
   504 }

   507 ngx_http_request_t *
   508 ngx_http_create_request(ngx_connection_t *c)
   509 {
   514     r = ngx_http_alloc_request(c);


   539 static ngx_http_request_t *
   540 ngx_http_alloc_request(ngx_connection_t *c)
   541 {
   549     hc = c->data;
   566     r->http_connection = hc;
   567     r->signature = NGX_HTTP_MODULE;
   568     r->connection = c;
   569     // 设置 配置上下文,也就是找到 server
   570     r->main_conf = hc->conf_ctx->main_conf;
   571     r->srv_conf = hc->conf_ctx->srv_conf;
   572     r->loc_conf = hc->conf_ctx->loc_conf;

ngx使用 default server 配置上下文,进行解析 报文,根据报文头 Host 字段,找虚拟机,更改当前请求的 server 配置上下文
ngx_http_process_request_line -> ngx_http_process_request_headers -> ngx_http_find_virtual_server

  2284 static ngx_int_t
  2285 ngx_http_find_virtual_server(ngx_connection_t *c,
  2286     ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
  2287     ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp)
  2288 {
  2295     cscf = ngx_hash_find_combined(&virtual_names->names,
  2296                                   ngx_hash_key(host->data, host->len),
  2297                                   host->data, host->len);
  2298
  2299     if (cscf) {
  2300         *cscfp = cscf;
  2301         return NGX_OK;
  2302     }
  2303

3. Location 定位

Location定位位于 http 处理 的 NGX_HTTP_FIND_CONFIG_PHASE 阶段

   497         case NGX_HTTP_FIND_CONFIG_PHASE:
   498             find_config_index = n;
   499
   500             ph->checker = ngx_http_core_find_config_phase;
   501             n++;
   502             ph++;
   503
   504             continue;

ngx 根据 r->uri 进行 location 定位,找到后修改 r->loc_conf

   948 ngx_int_t
   949 ngx_http_core_find_config_phase(ngx_http_request_t *r,
   950     ngx_http_phase_handler_t *ph)
   951 {
   960     rc = ngx_http_core_find_location(r);

  1393 static ngx_int_t
  1394 ngx_http_core_find_location(ngx_http_request_t *r)
  1395 {
  1405
  1406     pclcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
  1407
  1408     rc = ngx_http_core_find_static_location(r, pclcf->static_locations);

  1470 static ngx_int_t
  1471 ngx_http_core_find_static_location(ngx_http_request_t *r,
  1472     ngx_http_location_tree_node_t *node)
  1473 {
  1478     len = r->uri.len;
  1479     uri = r->uri.data;
  1483     for ( ;; ) {
  1495         rc = ngx_filename_cmp(uri, node->name, n);
  1496
  1497         if (rc != 0) {
  1498             node = (rc < 0) ? node->left : node->right;
  1499
  1500             continue;
  1501         }
            ...
  1503         if (len > (size_t) node->len) {
  1504
  1505             if (node->inclusive) {
  1506
  1507                 r->loc_conf = node->inclusive->loc_conf;   // 找到 loc 修改r->loc_conf
  1508                 rv = NGX_AGAIN;
  1509
  1510                 node = node->tree;
  1511                 uri += n;
  1512                 len -= n;
  1513
  1514                 continue;
  1515             }
  1516
  1517             /* exact only */
  1518
  1519             node = node->right;
  1520
  1521             continue;
  1522         }

posted on 2022-05-16 11:17  开心种树  阅读(81)  评论(0编辑  收藏  举报