Nginx模块开发小记

Friday, September 4th, 2009 @ 00:53

前阵子在折腾Nginx的模块, 很有趣.

为了方便使用调试器, 可以单进程非daemon方式启动, 使用参数:

daemon off;
master_process  off;

因为Nginx是事件驱动, 在读request body时, 第一个数据包一般发送不全, 需要异步读取余下的.

当在主handler部分调用ngx_http_read_client_request_body时, 需要注册一个回调的handler, 然后主handler直接返回NGX_DONE, 告诉Nginx留下这个请求的事件注册, 继续接收数据包.

经过若干次循环最终读完request body后, Nginx会去回调被注册的handler, 在此函数中产生响应, 最后调用ngx_http_finalize_request结束整个请求. 大概流程是:

ngx_http_foo_handler(){
    ngx_http_read_client_request_body(r, ngx_http_foo_post_handler);
    return NGX_DONE; // 主handler结束
}
ngx_http_foo_post_handler(){
    // 请求全部读完后从这里入口, 可以产生响应
    ngx_http_finalize_request(r, NGX_HTTP_OK);
}

一般的模块都是同步方式的, 我开始就没搞明白这异步读到底怎么搞, 走了不少弯路. 代码上可以简单参考dav模块, 复杂点还有upload模块.

Nginx可能会把request body放到两个buffer里面, 太大的话也可能存入文件中. 如果要在模块中读取request body进行处理, 自然不希望搞太麻烦,可以:

r->request_body_in_single_buf = 1;

使body存在一个buffer里面, 配置里面要留够需要的大小.

如果没有特殊的要求, 这类模块也可以拿 embedded perl 来写. 响应产生, sendfile都支持. Perl的开发效率自然很高, 维护也方便. 作者说此功能还是"experimental",  但实测了下没出啥问题.

我本着先写原型的目的试验了下, 结果发现性能还不错, 在双路5130机器上, perl版本的可以达到15k req/s (使用ab测试), 非常够用了.

Tags: , , , , ,
Posted in t | 4 Comments »

4 Responses to “Nginx模块开发小记”

  1. 大豆 says:

    黄牛的带头作用很强大,大家都写学术博了。。。。

  2. 兵临城下 says:

    这篇文章写的好,遇到了这个问题, 请问你用C实现了这样的上传接口了吗?

Leave a Reply