11.10.2 ngx_http_free_request

ngx_http_free_request方法将会释放请求对应的ngx_http_request_t数据结构,它并不会像ngx_http_close_connection方法一样去释放承载请求的TCP连接,每一个TCP连接可以反复地承载多个HTTP请求,因此,ngx_http_free_request是比ngx_http_close_connection更高层次的方法,前者必然先于后者调用。下面看看图11-23中ngx_http_free_request方法到底做了哪些工作。

11.10.2 ngx_http_free_request - 图1

图 11-23 ngx_http_free_request方法的流程图

在描述图11-23之前,先来看一个数据结构ngx_http_cleanup_t,它的定义如下。


typedef struct ngx_http_cleanup_s ngx_http_cleanup_t;

struct ngx_http_cleanup_s{

//由HTTP模块提供的清理资源的回调方法

ngx_http_cleanup_pt handler;

//希望给上面的handler方法传递的参数

void*data;

/一个请求可能会有多个ngx_http_cleanup_t清理方法,这些清理方法间就是通过next指针连接成单链表的/

ngx_http_cleanup_t*next;

};


事实上,任何一个请求的ngx_http_request_t结构体中都有一个ngx_http_cleanup_t类型的成员cleanup,如果没有需要清理的资源,则cleanup为空指针,否则HTTP模块可以向cleanup中以单链表的形式无限制地添加ngx_http_cleanup_t结构体,用以在请求结束时释放资源。再看看handler方法的定义,如下所示。


typedef void(ngx_http_cleanup_pt)(voiddata);


如果需要在请求释放时执行一些回调方法,首先需要实现一个ngx_http_cleanup_pt方法。当然,HTTP框架还很友好地提供了一个工具方法ngx_http_cleanup_add,用于向请求中添加ngx_http_cleanup_t结构体,其定义如下。


ngx_http_cleanup_tngx_http_cleanup_add(ngx_http_request_tr,size_t size)


这个方法返回的就是已经插入请求的ngx_http_cleanup_t结构体指针,其中data成员指向的内存都已经分配好,内存的大小由size参数指定。

注意 事实上,在3.8.2节中曾经简单地介绍过同样用于清理资源的ngx_pool_cleanup_t,它与ngx_http_cleanup_pt是不同的,ngx_pool_cleanup_t仅在所用的内存池销毁时才会被调用来清理资源,它何时释放资源将视所使用的内存池而定,而ngx_http_cleanup_pt是在ngx_http_request_t结构体释放时被调用来释放资源的。

下面说明一下ngx_http_free_request方法所做的3项主要工作。

1)循环地遍历请求ngx_http_request_t结构体中的cleanup链表,依次调用每一个ngx_http_cleanup_pt方法释放资源。

2)在11个ngx_http_phases阶段中,最后一个阶段叫做NGX_HTTP_LOG_PHASE,它是用来记录客户端的访问日志的。在这一步骤中,将会依次调用NGX_HTTP_LOG_PHASE阶段的所有回调方法记录日志。官方的ngx_http_log_module模块就是在这里记录access log的。

3)销毁请求ngx_http_request_t结构体中的pool内存池。在销毁内存池时,挂在该内存池下的由各Nginx模块实现的ngx_pool_cleanup_t方法也会被调用,注意它与第1步的区别。

注意 如果打开了统计HTTP请求的功能,ngx_http_free_request方法还会更新共享内存中的统计请求数量的两个原子变量:ngx_stat_reading、ngx_stat_writing,详见14.2.1节。