《深入剖析ngx》——请求处理

请求处理一定的流程是
创建监听套接字
接受连接
读取数据,解析请求

1. 监听套接字

1.1 加载配置——listen指令


ngx加载完 listen指令后会构造如上结构。
可见,ngx以 端口号为一个单位排布:
比如
80端口 : 127.0.0.1 192.168.1.1
8080端口: 192.168.1.4 192.168.2.3

加载完listen配置后,进行创建 监听套机字
ngx_http_block -> ngx_http_optimize_servers -> ngx_http_init_listening -> ngx_http_add_listening -> ngx_create_listening
cf->cycle->listening 数组增加 ngx_listening_t
所以配置初始化后,构造如下结构,

ngx_listening_t 对象就是描述监听相关,包含监听套接字,
并且 handler = ngx_http_init_connection

1.2 创建套接字

ngx_init_cycle 的 结尾部分调用 ngx_open_listening_sockets
ngx_open_listening_sockets 遍历 cycle->listening ,创建监听套接字(socket , bind , listen)

1.3 将监听套接字加入事件监听

完成监听套接字初始化后,进行fork,子进程继承监听套接字,子进程分别调用 ngx_event_process_init 将监听套接字加入事件监听。

   610 static ngx_int_t
   611 ngx_event_process_init(ngx_cycle_t *cycle)
   612 {
          ....
   776
   777     ls = cycle->listening.elts;
   778     for (i = 0; i < cycle->listening.nelts; i++) {
   786         c = ngx_get_connection(ls[i].fd, cycle->log);
   795         c->listening = &ls[i];
   796         ls[i].connection = c;
   865         rev->handler = (c->type == SOCK_STREAM) ? ngx_event_accept
   866                                                 : ngx_event_recvmsg;
   900         if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
   901             return NGX_ERROR;
   902         }
        }

可见,
在 ngx_listening_t 基础上封装了 ngx_connection_t 对象,用于描述连接。
ngx_connection_t 对象是 事件处理传递的 用户数据。
且 处理函数为 ngx_event_accept

2. 通信套接字

2.1 获得通信套接字

ngx_event_accept 获得 已连接套接字,并封装到 ngx_connection_t 对象中,初始化 ngx_connection_t 对象(内存池),调用 ngx_listening_t->handler.

2.2 将通信套接字加入事件监听

handler 为 ngx_http_init_connection

   206 void
   207 ngx_http_init_connection(ngx_connection_t *c)
   208 {
   210     ngx_event_t               *rev;
   215     ngx_http_connection_t     *hc;

          // 构造 ngx_http_connection_t  并初始化
 222     hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
  228     c->data = hc;

           // 设置 通信套接字读写回调
   324     rev = c->read;
   325     rev->handler = ngx_http_wait_request_handler;
   326     c->write->handler = ngx_http_empty_handler;

   334 #if (NGX_HTTP_SSL)
   335     {
   336     ngx_http_ssl_srv_conf_t  *sscf;
   337
   338     sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
   339
   340     if (sscf->enable || hc->addr_conf->ssl) {
   341         hc->ssl = 1;
   342         c->log->action = "SSL handshaking";
   343         rev->handler = ngx_http_ssl_handshake;
   344     }
   345     }
   346 #endif

           // 设置读超时
   365     cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
   366
   367     ngx_add_timer(rev, cscf->client_header_timeout);

           // 添加rev事件 到 事件监听
   370     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
   371         ngx_http_close_connection(c);
   372         return;
   373     }
   374 }

如上设置了多个回调
一般读回调 : ngx_http_wait_request_handler
写回调 :ngx_http_empty_handler
SSL读回调:ngx_http_ssl_handshake
读超时回调: cscf->client_header_timeout

3. 处理请求

3.1 读取数据

   377 static void
   378 ngx_http_wait_request_handler(ngx_event_t *rev)
   379 {
   408     b = c->buffer;
   432     n = c->recv(c, b->last, size);
   496     c->data = ngx_http_create_request(c);
   502     rev->handler = ngx_http_process_request_line;
   503     ngx_http_process_request_line(rev);
   504 }

ngx_http_wait_request_handler 确保读取完整数据,并构建 ngx_http_request_t

3.2 解析报文

ngx_http_process_request_line
ngx_http_parse_request_line : 解析 http 报文第一行
ngx_http_process_request_uri : 解析uri
ngx_http_process_request_headers : 解析headers
ngx_http_request_t -> headers_in -> headers 记录所有的header,
headers链表元素为 ngx_table_elt_t
ngx_http_run_posted_requests : 报文处理最后阶段

3.3 http模块处理请求

ngx_http_process_request_headers 完成解析 headers后,会调用 ngx_http_process_request->ngx_http_handler->ngx_http_core_run_phases 进行模块处理

   862 void
   863 ngx_http_core_run_phases(ngx_http_request_t *r)
   864 {
   865     ngx_int_t                   rc;
   866     ngx_http_phase_handler_t   *ph;
   867     ngx_http_core_main_conf_t  *cmcf;
   868
   869     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
   870
   871     ph = cmcf->phase_engine.handlers;
   872
   873     while (ph[r->phase_handler].checker) {
   874
   875         rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);
   876
   877         if (rc == NGX_OK) {
   878             return;
   879         }
   880     }
   881 }

最终会被 static 模块的 ngx_http_static_handler 处理,该函数调用 ngx_http_output_filter 进入filter模块。

4. 响应

ngx 先发送 response header , 再发送 response body

   48 static ngx_int_t
   49 ngx_http_static_handler(ngx_http_request_t *r)
   50 {
          ...
  249     rc = ngx_http_send_header(r);
  270     return ngx_http_output_filter(r, &out);
  271 }

  1830 ngx_int_t
  1831 ngx_http_send_header(ngx_http_request_t *r)
  1832 {
           ....
  1847
  1848     return ngx_http_top_header_filter(r);
  1849 }

  1852 ngx_int_t
  1853 ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
  1854 {
  1863     rc = ngx_http_top_body_filter(r, in);
  1870     return rc;
  1871 }

posted on 2022-04-26 16:31  开心种树  阅读(445)  评论(0编辑  收藏  举报