1 定义ngx_http_close_connection 函数 定义在 ./nginx-1.24.0/src/http/ngx_http_request.cvoidngx_http_close_connection(ngx_connection_t*c){ngx_pool_t*pool;ngx_log_debug1(NGX_LOG_DEBUG_HTTP,c-log,0,close http connection: %d,c-fd);#if(NGX_HTTP_SSL)if(c-ssl){if(ngx_ssl_shutdown(c)NGX_AGAIN){c-ssl-handlerngx_http_close_connection;return;}}#endif#if(NGX_STAT_STUB)(void)ngx_atomic_fetch_add(ngx_stat_active,-1);#endifc-destroyed1;poolc-pool;ngx_close_connection(c);ngx_destroy_pool(pool);}ngx_http_close_connection 函数用于 彻底关闭一个 HTTP 连接是连接生命周期的最后一步。2 详解1 函数签名voidngx_http_close_connection(ngx_connection_t*c)返回值类型void 该函数不向调用者返回任何值。参数 ngx_connection_t *c 一个指向 ngx_connection_t 结构体的指针。 该结构体是 Nginx 对每个 TCP 连接的抽象 函数需修改该连接的状态2 逻辑流程1 局部变量 2 调试日志 3 SSL 关闭处理 4 统计桩更新 5 关闭连接1 局部变量{ngx_pool_t*pool;2 调试日志ngx_log_debug1(NGX_LOG_DEBUG_HTTP,c-log,0,close http connection: %d,c-fd);3 SSL 关闭处理#if(NGX_HTTP_SSL)if(c-ssl){if(ngx_ssl_shutdown(c)NGX_AGAIN){c-ssl-handlerngx_http_close_connection;return;}}#endif判断当前连接是否启用了 SSL/TLS 层 若为非 SSL 明文连接跳过整个 SSL 关闭流程 若为 SSL 连接则必须执行 TLS 规范要求的关闭通知握手机制 调用 ngx_ssl_shutdown 启动 SSL 层面的优雅关闭握手。 该函数会尝试发送 close_notify 警报并向对端告知连接即将关闭。 因为 Nginx 工作在所有 socket 非阻塞模式下 该操作可能无法一次完成底层 TCP 发送缓冲区满或还需接收对方响应 此时返回 NGX_AGAIN 表示“需要稍后重试” 将 SSL 层的回调句柄 handler 设置为当前函数自身 当 SSL 关闭需要异步等待事件时Nginx 不阻塞 worker 进程。 而是约定当 socket 再次可读/写时事件模块会间接调用 c-ssl-handler。 这里将句柄指向自身形成一个可重入的状态机 下次事件触发时将继续执行本函数继续尝试 SSL 关闭握手直到彻底完成 立即从函数返回不执行后续的 socket 关闭和内存池销毁。 逻辑 因为 SSL 关闭尚未完成 底层 socket 仍需保持打开用以收发 close_notify 消息。 此时直接返回暂停清理流程等待事件驱动下一次调用4 统计桩更新#if(NGX_STAT_STUB)(void)ngx_atomic_fetch_add(ngx_stat_active,-1);#endif原子地将全局变量 ngx_stat_active 减 1 活跃连接计数器在连接建立时递增在此处递减精确反映当前正在处理的 HTTP 连接数5 关闭连接c-destroyed1;poolc-pool;ngx_close_connection(c);ngx_destroy_pool(pool);}#1 将连接结构体中的 destroyed 标志置为 1。 这是一个防止重入的守护标志。 在其他事件回调中如读/写完成处理会首先检查 c-destroyed 若已置 1 则直接返回避免对即将或已被回收的连接进行操作杜绝野指针和双重释放。#2 将连接的内存池地址保存到局部变量 pool 中 由于下一行 ngx_close_connection(c) 会回收 c 结构可能将字段清零或将其放回空闲链表 之后无法再通过 c-pool 安全地引用内存池。 提前保存保证了无论连接结构如何回收最终都能正确销毁整个内存池。#3 执行底层 TCP 连接的关闭和连接结构回收#4 销毁之前保存的连接内存池 pool。 该内存池为本次 HTTP 连接期间所有内存分配请求结构、缓冲、临时变量等提供记忆。 销毁它会一次性高效回收所有关联内存彻底完成连接生命周期末端的资源清理。 使用保存的 pool 而非 c-pool确保了调用安全。