12.6.2 默认的input_filter方法

如果HTTP模块没有实现input_filter方法,那么将使用ngx_http_upstream_non_buffered_filter方法作为input_filter,这个默认的方法将会试图在buffer缓冲区中存放全部的响应包体。

ngx_http_upstream_non_buffered_filter方法其实很简单,下面直接列出其主要代码来分析该方法。


static ngx_int_t ngx_http_upstream_non_buffered_filter(void*data,ssize_t bytes)

{

/前文说过,data参数就是ngx_http_upstream_t结构体中的input_filter_ctx,当HTTP模块未实现input_filter方法时,input_filter_ctx成员会指向请求的ngx_http_request_t结构体/

ngx_http_request_t*r=data;

ngx_buf_t*b;

ngx_chain_tcl,*ll;

ngx_http_upstream_t*u;

u=r->upstream;

/找到out_bufs链表的末尾,其中cl指向链表中最后一个ngx_chain_t元素的next成员,所以cl最后一定是NULL空指针,而ll指向最后一个缓冲区的地址,它用来在后面的代码中向out_bufs链表添加新的缓冲区/

for(cl=u->out_bufs,ll=&u->out_bufs;cl;cl=cl->next)

{

ll=&cl->next;

}

/free_bufs指向空闲的ngx_buf_t结构体构成的链表,如果free_bufs此时是空的,那么将会重新由r->pool内存池中分配一个ngx_buf_t结构体给cl;如果free_bufs链表不为空,则直接由free_bufs中获取一个ngx_buf_t结构体给cl/

cl=ngx_chain_get_free_buf(r->pool,&u->free_bufs);

if(cl==NULL){

return NGX_ERROR;

}

//将新分配的ngx_buf_t结构体添加到out_bufs链表的末尾

*ll=cl;

/修改新分配缓冲区的标志位,表明在内存中,flush标志位为可能发送缓冲区到客户端服务,参见12.7节/

cl->buf->flush=1;

cl->buf->memory=1;

//buffer缓冲区才是真正接收上游服务器响应包体的缓冲区

b=&u->buffer;

//last实际指向本次接收到的包体首地址

cl->buf->pos=b->last;

//last向后移动bytes字节,意味着buffer需要保存这次收到的包体

b->last+=bytes;

//last和pos成员确定了out_bufs链表中每个缓冲区的包体数据

cl->buf->last=b->last;

cl->buf->tag=u->output.tag;

/如果没有设置包体长度,u->length就是NGX_MAX_SIZE_T_VALUE,那么到这里结束/

if(u->length==NGX_MAX_SIZE_T_VALUE){

return NGX_OK;

}

//更新length,需要接收到的包体长度减少bytes字节

u->length-=bytes;

return NGX_OK;

}


可以看到,默认的input_filter方法会试图让独立的buffer缓冲区保存全部的包体,这就要求我们对上游服务器的响应包体大小有绝对正确的判断,否则一旦上游服务器发来的响应包体超过buffer缓冲区的大小,请求将会出错。

注意 对于上述这段代码的理解,可参见图12-8第4步中ngx_chain_update_chains方法的执行过程,它们是配对执行的。