如何开始学习Nginx模块开发?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1590个文字,预计阅读时间需要7分钟。
前言+Nginx是目前最流行的HTTP+Server之一,根据W3Techs的统计,目前世界排名前100万的网站中,Nginx的占有率为6.8%。与Apache相比,Nginx在处理高并发情况下具有巨大的性能优势。+Ng
前言Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%。与Apache相比,Nginx在高并发情况下具有巨大的性能优势。
Nginx属于典型的微内核设计,其内核非常简洁和优雅,同时具有非常高的可扩展性。Nginx最初仅仅主要被用于做反向代理,后来随着HTTP核心的成熟和各种HTTP扩展模块的丰富,Nginx越来越多被用来取代Apache而单独承担HTTP Server的责任,例如目前淘宝内各个部门正越来越多使用Nginx取代Apache,据笔者了解,在腾讯和新浪等公司也存在类似情况。
同时,大量的第三方扩展模块也令Nginx越来越强大。例如,由淘宝的工程师清无(王晓哲)和春来(章亦春)所开发的nginx_lua_module可以将Lua语言嵌入到Nginx配置中,从而利用Lua极大增强了Nginx本身的编程能力,甚至可以不用配合其它脚本语言(如PHP或Python等),只靠Nginx本身就可以实现复杂业务的处理。而春来所开发的ngx_openresty更是通过集成LuaJIT等组件,将Nginx本身变成了一个完全的应用开发平台。目前淘宝数据平台与产品部量子统计的产品都是基于ngx_openresty所开发。对ngxin_lua_module或ngx_openresty感兴趣的朋友可以参考我在关键词上给出的链接,后续我也可能会写一些与其有关的文章。
本文将会重点关注Nginx模块开发入门及基础。目前Nginx的学习资料非常少,而扩展模块开发相关的资料几乎只有《Emiller's Guide To Nginx Module Development》一文,此文十分经典,但是由于Nginx版本的演进,其中少许内容可能有点过时。本文是笔者在研读这篇文章和Nginx源代码的基础上,对自己学习Nginx模块开发的一个总结。本文将通过一个完整的模块开发实例讲解Nginx模块开发的入门内容。
本文将基于Nginx最新的1.0.0版本,操作系统环境为Linux(Ubuntu10.10)。
前言
Nginx提要
Nginx在Linux下的安装与运行
Nginx配置文件基本结构
Nginx模块工作原理概述
Nginx模块开发实战
定义模块配置结构
定义指令
创建合并配置信息
编写Handler
组合Nginx Module
Nginx模块的安装
Nginx更深入的学习
Nginx参考文献
Nginx提要开发Nginx扩展当然首要前提是对Nginx有一定的了解,然而本文并不打算详细阐述Nginx的方方面面,诸如Nginx的安装和各种详细配置等内容都可以在Nginx官网的Document中找到,本文在这里只会概括性描述一些后面可能会用到的原理和概念。
Nginx在Linux下的安装与运行使用Nginx的第一步是下载Nginx源码包,例如1.0.0的下载地址为nginx.org/download/nginx-1.0.0.tar.gz。下载完后用tar命令解压缩,进入目录后安装过程与Linux下通常步骤无异,例如我想讲Nginx安装到/usr/local/nginx下,则执行如下命令:
./configure --prefix=/usr/local/nginx make make install
安装完成后可以直接使用下面命令启动Nginx:
/usr/local/nginx/sbin/nginx
Nginx默认以Deamon进程启动,输入下列命令:
curl -i localhost/
就可以检测Nginx是否已经成功运行。或者也可以在浏览器中输入localhost/,应该可以看到Nginx的欢迎页面了。启动后如果想停止Nginx可以使用:
/usr/local/nginx/sbin/nginx -s stop
个人博客已迁移至www.codinglabs.org,本文全文最新地址为www.codinglabs.org/html/intro-of-nginx-module-development.html,欢迎访问!!!
Nginx配置文件基本结构配置文件可以看做是Nginx的灵魂,Nginx服务在启动时会读入配置文件,而后续几乎一切动作行为都是按照配置文件中的指令进行的,因此如果将Nginx本身看做一个计算机,那么Nginx的配置文件可以看成是全部的程序指令。
下面是一个Nginx配置文件的实例:
#user nobody; worker_processes 8; error_log logs/error.log; pid logs/nginx.pid; events { worker_connections 1024; } hostname/echo时会输出hello nginx。
直观来看,要实现这个功能需要三步:1、读入配置文件中echo指令及其参数;2、进行HTTP包装(添加HTTP头等工作);3、将结果返回给客户端。下面本文将分部介绍整个模块的开发过程。
定义模块配置结构首先我们需要一个结构用于存储从配置文件中读进来的相关指令参数,即模块配置信息结构。根据Nginx模块开发规则,这个结构的命名规则为ngx_linux.die.net/man/3/intptr_t。
定义指令一个Nginx模块往往接收一至多个指令,echo模块接收一个指令“echo”。Nginx模块使用一个ngx_command_t数组表示模块所能接收的所有模块,其中每一个元素表示一个条指令。ngx_command_t是ngx_command_s的一个别称(Nginx习惯于使用“_s”后缀命名结构体,然后typedef一个同名“_t”后缀名称作为此结构体的类型名),ngx_command_s定义在core/ngx_config_file.h中:
struct ngx_command_s { ngx_str_t name; ngx_uint_t type; char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); ngx_uint_t conf; ngx_uint_t offset; void *post; };
其中name是词条指令的名称,type使用掩码标志位方式配置指令参数,相关可用type定义在core/ngx_config_file.h中:
#define NGX_CONF_NOARGS 0x00000001 #define NGX_CONF_TAKE1 0x00000002 #define NGX_CONF_TAKE2 0x00000004 #define NGX_CONF_TAKE3 0x00000008 #define NGX_CONF_TAKE4 0x00000010 #define NGX_CONF_TAKE5 0x00000020 #define NGX_CONF_TAKE6 0x00000040 #define NGX_CONF_TAKE7 0x00000080 #define NGX_CONF_MAX_ARGS 8 #define NGX_CONF_TAKE12 (NGX_CONF_TAKE1|NGX_CONF_TAKE2) #define NGX_CONF_TAKE13 (NGX_CONF_TAKE1|NGX_CONF_TAKE3) #define NGX_CONF_TAKE23 (NGX_CONF_TAKE2|NGX_CONF_TAKE3) #define NGX_CONF_TAKE123 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3) #define NGX_CONF_TAKE1234 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3 \ |NGX_CONF_TAKE4) #define NGX_CONF_ARGS_NUMBER 0x000000ff #define NGX_CONF_BLOCK 0x00000100 #define NGX_CONF_FLAG 0x00000200 #define NGX_CONF_ANY 0x00000400 #define NGX_CONF_1MORE 0x00000800 #define NGX_CONF_2MORE 0x00001000 #define NGX_CONF_MULTI 0x00002000
其中NGX_CONF_NOARGS表示此指令不接受参数,NGX_CON F_TAKE1-7表示精确接收1-7个,NGX_CONF_TAKE12表示接受1或2个参数,NGX_CONF_1MORE表示至少一个参数,NGX_CONF_FLAG表示接受“on|off”……
set是一个函数指针,用于指定一个参数转化函数,这个函数一般是将配置文件中相关指令的参数转化成需要的格式并存入配置结构体。Nginx预定义了一些转换函数,可以方便我们调用,这些函数定义在core/ngx_conf_file.h中,一般以“_slot”结尾,例如ngx_conf_set_flag_slot将“on或off”转换为“1或0”,再如ngx_conf_set_str_slot将裸字符串转化为ngx_str_t。
conf用于指定Nginx相应配置文件内存其实地址,一般可以通过内置常量指定,如NGX_HTTP_LOC_CONF_OFFSET,offset指定此条指令的参数的偏移量。
下面是echo模块的指令定义:
static ngx_command_t ngx_localhost/echo
结果如下:
可以看到模块已经正常工作了,也可以在浏览器中打开网址,就可以看到结果:
更深入的学习本文只是简要介绍了Nginx模块的开发过程,由于篇幅的原因,不能面面俱到。因为目前Nginx的学习资料很少,如果读者希望更深入学习Nginx的原理及模块开发,那么阅读源代码是最好的办法。在Nginx源代码的core/下放有Nginx的核心代码,对理解Nginx的内部工作机制非常有帮助,wiki.nginx.org/3rdPartyModules上有大量优秀的第三方模块,也是非常好的学习资料。
如有意见建议或疑问欢迎发送邮件至ericzhang.buaa@gmail.com。希望本文对您有所帮助!!!
参考文献[1] Evan Miller, Emiller's Guide To Nginx Module Development. www.evanmiller.org/nginx-modules-guide.html, 2009
[2] wiki.nginx.org/Configuration
[3] Clément Nedelcu, Nginx Http Server. Packt Publishing, 2010
本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名张洋(包含链接),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系。
本文共计1590个文字,预计阅读时间需要7分钟。
前言+Nginx是目前最流行的HTTP+Server之一,根据W3Techs的统计,目前世界排名前100万的网站中,Nginx的占有率为6.8%。与Apache相比,Nginx在处理高并发情况下具有巨大的性能优势。+Ng
前言Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%。与Apache相比,Nginx在高并发情况下具有巨大的性能优势。
Nginx属于典型的微内核设计,其内核非常简洁和优雅,同时具有非常高的可扩展性。Nginx最初仅仅主要被用于做反向代理,后来随着HTTP核心的成熟和各种HTTP扩展模块的丰富,Nginx越来越多被用来取代Apache而单独承担HTTP Server的责任,例如目前淘宝内各个部门正越来越多使用Nginx取代Apache,据笔者了解,在腾讯和新浪等公司也存在类似情况。
同时,大量的第三方扩展模块也令Nginx越来越强大。例如,由淘宝的工程师清无(王晓哲)和春来(章亦春)所开发的nginx_lua_module可以将Lua语言嵌入到Nginx配置中,从而利用Lua极大增强了Nginx本身的编程能力,甚至可以不用配合其它脚本语言(如PHP或Python等),只靠Nginx本身就可以实现复杂业务的处理。而春来所开发的ngx_openresty更是通过集成LuaJIT等组件,将Nginx本身变成了一个完全的应用开发平台。目前淘宝数据平台与产品部量子统计的产品都是基于ngx_openresty所开发。对ngxin_lua_module或ngx_openresty感兴趣的朋友可以参考我在关键词上给出的链接,后续我也可能会写一些与其有关的文章。
本文将会重点关注Nginx模块开发入门及基础。目前Nginx的学习资料非常少,而扩展模块开发相关的资料几乎只有《Emiller's Guide To Nginx Module Development》一文,此文十分经典,但是由于Nginx版本的演进,其中少许内容可能有点过时。本文是笔者在研读这篇文章和Nginx源代码的基础上,对自己学习Nginx模块开发的一个总结。本文将通过一个完整的模块开发实例讲解Nginx模块开发的入门内容。
本文将基于Nginx最新的1.0.0版本,操作系统环境为Linux(Ubuntu10.10)。
前言
Nginx提要
Nginx在Linux下的安装与运行
Nginx配置文件基本结构
Nginx模块工作原理概述
Nginx模块开发实战
定义模块配置结构
定义指令
创建合并配置信息
编写Handler
组合Nginx Module
Nginx模块的安装
Nginx更深入的学习
Nginx参考文献
Nginx提要开发Nginx扩展当然首要前提是对Nginx有一定的了解,然而本文并不打算详细阐述Nginx的方方面面,诸如Nginx的安装和各种详细配置等内容都可以在Nginx官网的Document中找到,本文在这里只会概括性描述一些后面可能会用到的原理和概念。
Nginx在Linux下的安装与运行使用Nginx的第一步是下载Nginx源码包,例如1.0.0的下载地址为nginx.org/download/nginx-1.0.0.tar.gz。下载完后用tar命令解压缩,进入目录后安装过程与Linux下通常步骤无异,例如我想讲Nginx安装到/usr/local/nginx下,则执行如下命令:
./configure --prefix=/usr/local/nginx make make install
安装完成后可以直接使用下面命令启动Nginx:
/usr/local/nginx/sbin/nginx
Nginx默认以Deamon进程启动,输入下列命令:
curl -i localhost/
就可以检测Nginx是否已经成功运行。或者也可以在浏览器中输入localhost/,应该可以看到Nginx的欢迎页面了。启动后如果想停止Nginx可以使用:
/usr/local/nginx/sbin/nginx -s stop
个人博客已迁移至www.codinglabs.org,本文全文最新地址为www.codinglabs.org/html/intro-of-nginx-module-development.html,欢迎访问!!!
Nginx配置文件基本结构配置文件可以看做是Nginx的灵魂,Nginx服务在启动时会读入配置文件,而后续几乎一切动作行为都是按照配置文件中的指令进行的,因此如果将Nginx本身看做一个计算机,那么Nginx的配置文件可以看成是全部的程序指令。
下面是一个Nginx配置文件的实例:
#user nobody; worker_processes 8; error_log logs/error.log; pid logs/nginx.pid; events { worker_connections 1024; } hostname/echo时会输出hello nginx。
直观来看,要实现这个功能需要三步:1、读入配置文件中echo指令及其参数;2、进行HTTP包装(添加HTTP头等工作);3、将结果返回给客户端。下面本文将分部介绍整个模块的开发过程。
定义模块配置结构首先我们需要一个结构用于存储从配置文件中读进来的相关指令参数,即模块配置信息结构。根据Nginx模块开发规则,这个结构的命名规则为ngx_linux.die.net/man/3/intptr_t。
定义指令一个Nginx模块往往接收一至多个指令,echo模块接收一个指令“echo”。Nginx模块使用一个ngx_command_t数组表示模块所能接收的所有模块,其中每一个元素表示一个条指令。ngx_command_t是ngx_command_s的一个别称(Nginx习惯于使用“_s”后缀命名结构体,然后typedef一个同名“_t”后缀名称作为此结构体的类型名),ngx_command_s定义在core/ngx_config_file.h中:
struct ngx_command_s { ngx_str_t name; ngx_uint_t type; char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); ngx_uint_t conf; ngx_uint_t offset; void *post; };
其中name是词条指令的名称,type使用掩码标志位方式配置指令参数,相关可用type定义在core/ngx_config_file.h中:
#define NGX_CONF_NOARGS 0x00000001 #define NGX_CONF_TAKE1 0x00000002 #define NGX_CONF_TAKE2 0x00000004 #define NGX_CONF_TAKE3 0x00000008 #define NGX_CONF_TAKE4 0x00000010 #define NGX_CONF_TAKE5 0x00000020 #define NGX_CONF_TAKE6 0x00000040 #define NGX_CONF_TAKE7 0x00000080 #define NGX_CONF_MAX_ARGS 8 #define NGX_CONF_TAKE12 (NGX_CONF_TAKE1|NGX_CONF_TAKE2) #define NGX_CONF_TAKE13 (NGX_CONF_TAKE1|NGX_CONF_TAKE3) #define NGX_CONF_TAKE23 (NGX_CONF_TAKE2|NGX_CONF_TAKE3) #define NGX_CONF_TAKE123 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3) #define NGX_CONF_TAKE1234 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3 \ |NGX_CONF_TAKE4) #define NGX_CONF_ARGS_NUMBER 0x000000ff #define NGX_CONF_BLOCK 0x00000100 #define NGX_CONF_FLAG 0x00000200 #define NGX_CONF_ANY 0x00000400 #define NGX_CONF_1MORE 0x00000800 #define NGX_CONF_2MORE 0x00001000 #define NGX_CONF_MULTI 0x00002000
其中NGX_CONF_NOARGS表示此指令不接受参数,NGX_CON F_TAKE1-7表示精确接收1-7个,NGX_CONF_TAKE12表示接受1或2个参数,NGX_CONF_1MORE表示至少一个参数,NGX_CONF_FLAG表示接受“on|off”……
set是一个函数指针,用于指定一个参数转化函数,这个函数一般是将配置文件中相关指令的参数转化成需要的格式并存入配置结构体。Nginx预定义了一些转换函数,可以方便我们调用,这些函数定义在core/ngx_conf_file.h中,一般以“_slot”结尾,例如ngx_conf_set_flag_slot将“on或off”转换为“1或0”,再如ngx_conf_set_str_slot将裸字符串转化为ngx_str_t。
conf用于指定Nginx相应配置文件内存其实地址,一般可以通过内置常量指定,如NGX_HTTP_LOC_CONF_OFFSET,offset指定此条指令的参数的偏移量。
下面是echo模块的指令定义:
static ngx_command_t ngx_localhost/echo
结果如下:
可以看到模块已经正常工作了,也可以在浏览器中打开网址,就可以看到结果:
更深入的学习本文只是简要介绍了Nginx模块的开发过程,由于篇幅的原因,不能面面俱到。因为目前Nginx的学习资料很少,如果读者希望更深入学习Nginx的原理及模块开发,那么阅读源代码是最好的办法。在Nginx源代码的core/下放有Nginx的核心代码,对理解Nginx的内部工作机制非常有帮助,wiki.nginx.org/3rdPartyModules上有大量优秀的第三方模块,也是非常好的学习资料。
如有意见建议或疑问欢迎发送邮件至ericzhang.buaa@gmail.com。希望本文对您有所帮助!!!
参考文献[1] Evan Miller, Emiller's Guide To Nginx Module Development. www.evanmiller.org/nginx-modules-guide.html, 2009
[2] wiki.nginx.org/Configuration
[3] Clément Nedelcu, Nginx Http Server. Packt Publishing, 2010
本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名张洋(包含链接),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系。

