nginx模块开发?
大部分情况下我们对于nginx的使用包括负载均衡、流量切换,使用nginx本身灵活的配置文件也基本上都能满足需求,但是在某些情况下就不太足够了,比如说对于ip快速的封禁&解封,当然了使用nginx本身的deny指令在某种情况下也能实现这种效果,但是需要对nginx进行频繁的reload,在某种程度上并不是最优解,这种情况下就需要nginx有一个模块他能支持对于nginx访问ip快速便捷的修改并且保证原本服务不受影响:)
这里说一句题外话,以我现有的经验和理解,在我看来programmer+computer的组合目标是在于将信息以高效的方式进行处理、传播与整合,互联网行业不同的职位则是从不同层面去处理信息,例如从应用层面处理信息最典型的例如http服务,细粒度的就是代码级别对信息的处理,例如各个公司程序员做的事情,当然了这中间还有一层就是使用shell来处理信息例如grep、awk等,从这种角度来看这个需求的话nginx实现对于ip的封禁需求确实从代码层面去做逻辑控制是最优的。
nginx以其高效、灵活闻名于世,相应的其优点是建立在其优雅&高度模块化&良好设计的代码之上,因此nginx模块开发上手还是比较容易的。
简单介绍
这里先推荐两个站点,对于入门以及平时开发十分有帮助:
这里主要说一下nginx对于lib的封装简直到了神一般的境界,甚至可以说开发nginx模块使用的是nginx-c语言了。。。
首先对于字符串的处理,nginx是这样处理的:
1 | #定义了一个结构体用来存储字符串的起始指针地址,以及该字符串的长度 |
而这样定义的原因是:在数据的处理中频繁的对字符串进行复制,处理传输,涉及到的malloc会大大影响性能(考虑一下c++ string),因此使用指针+长度这种方式来对字符串进行处理、复制其代价只是相当于操作一个整形变量。膜拜
nginx的设计可见一斑!
相应的nginx还有自己的buff类型pool类型,有兴趣的同学可以自己看一下文档。
代码结构
nginx本身相当于是一个http工厂,我们开发一个新的模块相当于是把一个机器加到了nginx的流水线上,模块应该是有7(具体数字记不清楚了)个注册点,在代码中指定该模块在那一层调用,然后在模块的内部定义中注册希望调用的函数,这个函数可以看作是我们代码逻辑的入口,相应的还有读取配置这一层逻辑,整理一下就是:
- 模块本身的定义
- 包括模块版本
- 模块的上下文信息
- 注册处理配置文件的函数
- 注册处理请求的函数
- 模块需要读取的配置文件信息
下面以一段hello world为例:
1 |
|
编译
以上代码写完之后,我们将代码命名为ngx_http_hello_world_module,在nginx源码文件夹src下面新建一个同名文件夹将代码放入,同时在ngx_http_hello_world_module文件夹下面创建一个config文件内容为:
1 | ngx_addon_name=ngx_http_hello_world_module |
做到这一步,我们的模块就准备完毕了,然后就是进行代码的编译了,这里我们需要通过再执行./configure的时候指定参数–add-module=src/ngx_http_hello_world_module 将我们的模块编译进去,完成之后make崭新的bin文件就诞生在obj文件夹下面了
运行
配置文件也要做少许修改
1 | location /hello { |
调试
最后就是调试这一步了,这里有两点需要注意一下:
- 使用单独的配置文件
- 使用非daemon模式运行,便于查看输出信息
最终完整版配置文件如下:
1 |
|
执行的命令如下:
1 | ./objs/nginx -p ./ -c conf/nginx.conf |
至此一个最简单的nginx模块就出来了,后面涉及到复杂的模块开发还会涉及到gdb之类工具的使用,今天就先写这些:)
转载请注明来源链接 http://just4fun.im/2017/10/28/nginx-模块开发复习笔记/ 尊重知识,谢谢:)