Nginx模块开发小记

前阵子在折腾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测试), 非常够用了.

This entry was posted in tech and tagged , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

2 Comments

  1. Posted 2009-9-4 at 09:38 | Permalink

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

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>