Hello!
2014-07-25 1:50 GMT-07:00 冰河:
> 假设ngx_http_sub_body_filter函数的输入参数in,当包含所有要发送到客户端数据的chain都经过该filter后,
> 总会有还有一个chain,而且该chain只包含一个buf ,该buf的pos、last、star、end、in_file都为0,只有last_buf
> 为1,请问一下,这个chain是怎么来的啊?这样的buf有什么作用啊?
>
这样的 buf 在 nginx 术语中属于“special buf”,用来标记主请求响应体数据流的末尾。响应体数据流一般会由一个或多个
chainlink/buf 构成。输出过滤器链在一个请求的生命期中也可能会被调用多次,所以我们需要 last_buf 来标记流的末尾。
值得一提的是,对于子请求的响应体流,应当改用 last_in_chain 标志,而不是 last_buf 标志。
> 问题2:
> 阅读ngx_http_sub_body_filter函数的代码发现,上述的buf最终会进入到如下的代码片段中
>
> if (ctx->buf->last_buf || ctx->buf->flush
> || ngx_buf_in_memory(ctx->buf))
> {
>
>
> if (b == NULL) {
> cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
> if (cl == NULL) {
> return NGX_ERROR;
> }
>
> b = cl->buf;
>
> ngx_memzero(b, sizeof(ngx_buf_t));
>
> b->sync = 1;
>
> *ctx->last_out = cl;
> ctx->last_out = &cl->next;
> }
>
> b->last_buf = ctx->buf->last_buf;
> b->flush = ctx->buf->flush;
> b->shadow = ctx->buf;
>
> b->recycled = ctx->buf->recycled;
> }
>
> 我的疑惑是,该filter为什么要自己重新生成一个chain和buf,然后把 ”问题1“ 中buf的标志位都拷贝到
> 自己重新生成的buf中,直接就把 “问题1” 中的chain发送出去不可以吗??
>
我之前给你的一封邮件里已说过了,sub filter 需要并且可能对输入数据进行修改,所以它在设计对输入和输出 buf
有较为严格的隔离(它们只通过 ->shadow 建立关联)。
> if (ctx->buf->last_buf || ctx->buf->flush
> || ngx_buf_in_memory(ctx->buf))
> {
> ===================
> 如果该判断条件成立是因为ngx_buf_in_memory(ctx->buf)为1,其余两项都为0,
> 那么如下的代码中岂不是会丢掉原buf的数据么?
> 如下代码中并没有把原buf的数据拷贝到新buf中啊?
不会。此时 b 不会为 NULL(如果确实有数据需要保留的话)。
> b->sync = 1;
> =============
> buf 中的sync字段有什么作用啊?
> =============
让当前的 buf 成为没有用户数据的“special buf”,否则的话,nginx 会抛出“zero size buf in
writer” 这样的 alert 错误消息。
> =============
> buf 中的recycled 有什么作用啊?
> =============
标记 buf 是经过回收的。它在 write filter 里和 b->flush 标记有类似的作用,即强制刷 nginx 自己的写缓冲。
Regards,
-agentzh