《深入剖析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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?