最近在结合《深入理解nginx》这本书学习nginx,现在记录下学习的一些心得。本书的第三章主要讲述的是如何在ngin
最近在结合《深入理解nginx》这本书学习nginx,现在记录下学习的一些心得。
本书的第三章主要讲述的是如何在nginx中开发和集成第三方http模块,流程大致如下:
1.定义自己的http模块
在nginx的安装目录下创建一个单独的文件夹my_http,在文件夹中新建my_test.c,需要在my_test.c文件中编写第三方模块的程序,如下:#include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r); static char * ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); //处理配置项 static ngx_command_t ngx_http_mytest_commands[] = { { ngx_string("mytest"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_NOARGS, ngx_http_mytest, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL }, ngx_null_command }; //模块上下文 static ngx_http_module_t ngx_http_mytest_module_ctx = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; //新模块定义 ngx_module_t ngx_http_mytest_module = { NGX_MODULE_V1, &ngx_http_mytest_module_ctx, ngx_http_mytest_commands, NGX_HTTP_MODULE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NGX_MODULE_V1_PADDING }; //配置项对应的回调函数 static char * ngx_http_mytest(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_mytest_handler; return NGX_CONF_OK; } //实际完成处理的回调函数 static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r) { if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } ngx_int_t rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } ngx_str_t type = ngx_string("text/plain"); ngx_str_t response = ngx_string("Hello World"); r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = response.len; r->headers_out.content_type = type; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } ngx_buf_t *b; b = ngx_create_temp_buf(r->pool, response.len); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_memcpy(b->pos, response.data, response.len); b->last = b->pos + response.len; b->last_buf = 1; ngx_chain_t out; out.buf = b; out.next = NULL; return ngx_http_output_filter(r, &out); }如上所示,要在nginx的框架中嵌入第三方的http 模块,主要的工作就是给ngx_module_t这个结构体去填充内容。而这个结构体中最关键的是ctx commands[]这样两个成员。详见《深入理解nginx》。ngx_http_mytest_handler函数中应当包含业务逻辑的具体实现。
2.编写config文件
为了将我们实现的第三方模块编译进Nginx的系统框架中,我们需要在my_http文件夹中编写config文件,其内容如下:
ngx_addon_name=ngx_http_mytest_moduleHTTP_MODULES="$HTTP_MODULES ngx_http_mytest_module"ngx_addon_dir=/root/unix/nginx-1.9.14/my_httpNGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/my_test.c"
新建模块的名字是ngx_http_mytest_module,该模块实现代码的路径是位于/root/unix/nginx-1.9.14/my_http
3.修改nginx.conf
修改/usr/local/nginx/conf目录下的nginx.conf文件,添加
location /test { mytest; }
这样,当nginx模块解析到/test这样的http请求的时候,就会对应到我们之前实现的第三方模块(与ngx_http_mytest_commands中的"mytest"相对应)。
4.编译
./configure --add-module=/root/unix/nginx-1.9.14/my_http
make install
5.运行
/usr/local/nginx/sbin/nginx
运行的时候遇到了小问题:bind (: : : , 80),提示adress already in use。
这是因为我的系统中当前后台还有正在运行的程序占据了80号端口。
使用netstat -anop | grep 80这个指令就可以知道当前占用80号端口的进程,然后kill 该进程的pid即可
最后进行测试:
可知我们自己实现的第三方http模块已经被集成到了nginx的框架中