最近在研究如何利用 Nginx 实现高性能网关,这里记录一下开发 Nginx 扩展模块 Hello World。
编译安装 Nginx 下载 Nginx 源代码,解压,进入源代码目录:
1 2 3 wget http://nginx.org/download/nginx-1.13.10.tar.gz tar zvxf nginx-1.13.10.tar.gz cd nginx-1.13.10
编译,安装 Nginx 到指定目录:
1 2 3 ./configure --prefix=/home/lihao/code/nginx/nginx-1.13.10/bin make make install
configure
命令中使用了参数 --prefix=/home/lihao/code/nginx/nginx-1.13.10/bin
是指将 Nginx 安装到目录 /home/lihao/code/nginx/nginx-1.13.10/bin
。
修改 /home/lihao/code/nginx/nginx-1.13.10/bin/conf/nginx.conf
,调整 Nginx 监听端口为 5123
:
1 2 3 server { listen 5123; server_name localhost;
启动 Nginx:
1 2 cd /home/lihao/code/nginx/nginx-1.13.10/bin./sbin/nginx
打开浏览器,地址栏输入:http://服务器 ip:5123/
可以正常看到 Nginx 的欢迎页面。
开发 Nginx 模块 创建目录 ngx_http_hello_world_module
,然后在该目录创建两个文件 config
和 ngx_http_hello_world_module.c
。
config
文件config
文件是个 shell 文件,用于告诉 Nginx 如何编译模块源代码。在 config
文件中,检测了当前 Nginx 版本是否支持动态模块,并采取不同的添加模块的方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ngx_addon_name=ngx_http_hello_world_module if test -n "$ngx_module_link " ; then ngx_module_type=HTTP ngx_module_name=ngx_http_hello_world_module ngx_module_srcs="$ngx_addon_dir /ngx_http_hello_world_module.c" . auto/module else HTTP_MODULES="$HTTP_MODULES ngx_http_hello_world_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir /ngx_http_hello_world_module.c" fi
C 模块文件 ngx_http_hello_world_module.c
用于实现自定义模块。
首先是函数 ngx_http_hello_world
的声明,这个函数会在源代码最后进行定义。
ngx_http_hello_world_commands
是个静态数组,用于定义 Nginx 指令。这里只定义一个指令 print_hello_world
,指令不需要参数,故定义为 NGX_CONF_NOARGS
。
ngx_http_hello_world_module_ctx
是个静态数组,用于定义函数,这些函数会在特定时刻执行,这里不需要,故都定义为 NULL
。
ngx_http_hello_world_module
是个静态数组,用于定义模块相关信息。
ngx_http_hello_world_handler
是模块的核心,实现在浏览器打印 Hello World!
。
最后是 ngx_http_hello_world
的定义,clcf->handler = ngx_http_hello_world_handler;
用于告诉 Nginx 自定义 handler ngx_http_hello_world_handler
。
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 #include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> static char *ngx_http_hello_world (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ;static ngx_command_t ngx_http_hello_world_commands[] = { { ngx_string("print_hello_world" ), NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, ngx_http_hello_world, 0 , 0 , NULL }, ngx_null_command }; static ngx_http_module_t ngx_http_hello_world_module_ctx = { NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL }; ngx_module_t ngx_http_hello_world_module = { NGX_MODULE_V1, &ngx_http_hello_world_module_ctx, ngx_http_hello_world_commands, NGX_HTTP_MODULE, NULL , NULL , NULL , NULL , NULL , NULL , NULL , NGX_MODULE_V1_PADDING }; static ngx_int_t ngx_http_hello_world_handler (ngx_http_request_t *r) { u_char *ngx_hello_world = (u_char *) "Hello World!" ; size_t sz = strlen ((const char *)ngx_hello_world); r->headers_out.content_type.len = strlen ("text/html" ) - 1 ; r->headers_out.content_type.data = (u_char *) "text/html" ; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = sz; ngx_http_send_header(r); ngx_buf_t *b; ngx_chain_t *out; b = ngx_calloc_buf(r->pool); out = ngx_alloc_chain_link(r->pool); out->buf = b; out->next = NULL ; b->pos = ngx_hello_world; b->last = ngx_hello_world + sz; b->memory = 1 ; b->last_buf = 1 ; return ngx_http_output_filter(r, out); } static char *ngx_http_hello_world (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_core_loc_conf_t *clcf; clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf->handler = ngx_http_hello_world_handler; return NGX_CONF_OK; }
编译模块源代码 在 Nginx 源代码目录,执行命令:
1 2 3 ./configure --prefix=/home/lihao/code/nginx/nginx-1.13.10/bin --add-dynamic-module=/home/lihao/code/nginx/ngx_http_hello_world_module make make install
可以看到 Nginx 安装目录下 modules
目录,增加了 ngx_http_hello_world_module.so
文件。
使用模块 修改 Nginx 安装目录下的 nginx.conf
文件,在 server
下添加:
1 2 3 location /test { print_hello_world; }
打开浏览器,地址栏输入:http://服务器 ip:5123/test
,可以看到页面输出:Hello World!
。
参考资料