IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

nginx模块开发

Skiyo 2010-12-21 01:52:06 累计浏览 5,662 次
本机暂存

因为一些需要,我也开始涉及nginx的模块开发,在看了一些资料后,写了自己第一个nginx模块。

其实nginx模块开发还算比较容易,网上开源的模块已经很多,都可以借鉴,令我震惊的是OAuth的模块都有。

nginx模块比较起来一些后端语言的实现,最重要的特点就是速度快了,这个无可厚非,nginx模块与apache的区别就是,apache是加载so模块,而nginx是直接将模块编译到主程序里。在我的简单测试下,一个业务逻辑非常简单的模块,可以达到1-2w/s的请求,如果你的机器够好,这个数据更加可观。对于一个PHP来说,能压到5000/s就非常不错了。

个人觉得nginx现在模块开发资料还比较少(貌似跟上面说的有些矛盾= =),开发起来还是磕磕绊绊的,所以如果大家想尝试一些nginx模块开发,并且运用到生产环境,推荐一些业务逻辑比较简单的时候再考虑。

nginx模块开发还有个优点就是部署起来非常容易,编译也非常简单。

好了 废话就不说了,下面给出一个hello world的demo。网上已经有了很多hello world的例子了 在我看来 还是很复杂。我还是自己来说一遍吧。

在开发模块之前,我们需要新建一个名为“config”的文件,在nginx编译的时候,来告知主程序把我这个模块也编译了。

在这个hello world的例子中,config类似于下面这个样子的:

1
2
3
ngx_addon_name=ngx_hello_world_module
HTTP_AUX_FILTER_MODULES="$HTTP_MODULES ngx_hello_world_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_hello_world_module.c"

需要注意的就是模块的名字跟你模块源码的位置

然后在你的这个目录下 新建ngx_hello_world_module.c

然后输入以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <ngx_core.h>
#include <ngx_http.h>
#include <nginx.h>
 
static char *ngx_hello_world(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_hello_world_get_output(ngx_http_request_t *r, char *out_buf);
static ngx_int_t ngx_hello_world_handler(ngx_http_request_t *r);
 
/* Commands */
static ngx_command_t  ngx_hello_world_commands[] = {
    { ngx_string("ngx_hello_world"),
      NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
      ngx_hello_world,
      NGX_HTTP_LOC_CONF_OFFSET,
      0,
      NULL },
 
      ngx_null_command
};
 
static ngx_http_module_t  ngx_hello_world_module_ctx = {
    NULL,                                  /* preconfiguration */
    NULL,                                     /* postconfiguration */
 
    NULL,                                  /* create main configuration */
    NULL,                                  /* init main configuration */
 
    NULL,                                  /* create server configuration */
    NULL,                                  /* merge server configuration */
 
    NULL,                                  /* create location configuration */
    NULL                                   /* merge location configuration */
};
 
/* hook */
ngx_module_t  ngx_hello_world_module = {
    NGX_MODULE_V1,
    &ngx_hello_world_module_ctx,              /* module context */
    ngx_hello_world_commands,                 /* module directives */
    NGX_HTTP_MODULE,                       /* module type */
    NULL,                                  /* init master */
    NULL,                                  /* init module */
    NULL,             /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    NULL,             /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};
 
 
static ngx_int_t ngx_hello_world_get_output(ngx_http_request_t *r, char *out_buf){
 
    sprintf(out_buf, "%s", "Hello World!");
    return NGX_OK;
}
 
static ngx_int_t
ngx_hello_world_handler(ngx_http_request_t *r)
{
    ngx_int_t     rc;
    ngx_buf_t    *b;
    ngx_chain_t   out;
 
    /* Http Output Buffer */
    char out_buf[20] = {0};
 
    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
        return NGX_HTTP_NOT_ALLOWED;
    }
 
    rc = ngx_http_discard_request_body(r);
 
    if (rc != NGX_OK && rc != NGX_AGAIN) {
        return rc;
    }
    //定制头信息
    r->headers_out.content_type.len = sizeof("text/html") - 1;
    r->headers_out.content_type.data = (u_char *) "text/html";
 
    if (r->method == NGX_HTTP_HEAD) {
        rc = ngx_http_send_header(r);
 
        if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
            return rc;
        }
    }
 
    //获取输出的body
    ngx_hello_world_get_output(r, out_buf);
 
    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
    if (b == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
 
    out.buf = b;
    out.next = NULL;
 
    b->pos = (u_char *)out_buf;
    b->last = (u_char *)out_buf + strlen(out_buf);
    b->memory = 1;
    b->last_buf = 1;
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = strlen(out_buf);
 
    rc = ngx_http_send_header(r);
 
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
        return rc;
    }
 
    return ngx_http_output_filter(r, &out);
}
 
static char *
ngx_hello_world(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t *clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
 
    /* register hanlder */
    clcf->handler = ngx_hello_world_handler;
 
    return NGX_CONF_OK;
}

然后编译。
编译需要弄明白的就是,我们不用编译我们的模块,我们只需要在编译nginx的时候 加上-add-module的参数就可以了。

另外,nginx的rewrite是需要用到pcre库的,所以编译nginx前,请先编译安装好pcre。

然后到nginx的目录下,进行configure

以下是代码片段:

./configure --prefix=/home/www/nginx --user=www --group=www --add-module=/home/www/download/ngx_hello_world --with-cc-opt="-I /home/www/pcre/include" --with-ld-opt="-L /home/www/pcre/lib"
-add-module后面就是我们模块的目录地址 此目录中包含刚才写的config文件, 后面的两个是指定pcre的目录,如果你configure的pcre的时候没有指定安装目录,则可以去掉这两个参数。

编译完成后,我们的模块就和nginx主程序“合体”了。

这时候我们进入nginx.conf 在你的server块中 加入以下信息:

 
1
2
3
location /hello {
	ngx_hello_world;
}

然后启动nginx, 这时候打开你的server/hello 就可以看到输出hello world的信息了。如果你感兴趣,可以用PHP来写个Hello World,然后来压一下比较一下性能:)

下面是本模块打包下载:

ngx_hello_world

同分类推荐文章

  1. Vibe新开源项目 - Vaala AI Gateway (2026-05-17 02:10:19)
  2. SmartPerfetto 架构文章 Q&amp;A:8 个深度技术问答 (2026-04-10 11:00:00)
  3. 让 AI 把我的 PHP 博客重写成 Go (2026-03-27 18:33:54)

查看更多 后端 文章 →

建议继续学习

  1. 配置Nginx+uwsgi更方便地部署python应用 (累计阅读 106,963)
  2. 搜狐闪电邮箱的 Nginx/Postfix 使用模式 (累计阅读 33,821)
  3. 记录一个软中断问题 (累计阅读 16,885)
  4. 解析nginx负载均衡 (累计阅读 16,503)
  5. server日志的路径分析 (累计阅读 11,181)
  6. Nginx模块开发入门 (累计阅读 11,101)
  7. 检查nginx配置,重载配置以及重启的方法 (累计阅读 10,782)
  8. Cacti 添加 Nginx 监控 (累计阅读 10,521)
  9. 使用Squid缓存视频 (累计阅读 10,280)
  10. fsockopen 异步处理 (累计阅读 10,280)