零基础开发 nginx 模块

简介: 推荐学习资料: * nginx 开发指南: http://nginx.org/en/docs/dev/development_guide.html * nginx 动态模块编译博客文章: https://www.nginx.com/blog/compiling-dynamic-modules-nginx-plus/ * nginx 源码: https://github.com/nginx

推荐学习资料:

本文大纲:

  1. 简要介绍 Nginx 动态模块 。
  2. 快速搭建简单 开发环境 ,拉取源码并编译 nginx 。
  3. 简要介绍 nginx 模块 源码配置与目录结构 ,建立工程框架。
  4. 简要介绍 nginx HTTP 模块结构,建立 一个 HTTP 空模块 框架代码。
  5. 编写一个简单配置文件,支持以普通用户 测试运行 nginx ,方便后续开发测试。
  6. 通过一个 hello world 示例简要介绍 Nginx 配置指令 。
  7. 简要介绍 Nginx HTTP 请求处理器 。
  8. 简要介绍 Nginx 热更新 (reload) 高级功能。
  9. 吐槽与闲聊 。

Nginx 动态模块

早期版本的 nginx 如果要扩展功能,新增代码必须和 nginx 主体代码一起编译成一个二进制文件,这显然非常不方便。2016 年 nginx 1.9.11 终于开始支持动态模块 (Linux 下动态模块即 so 文件),nginx 1.11.5 起支持单独编译动态模块 (而不必同时编译 nginx 自身),同时引入支持开源版本 nginx 与 nginx plus 的二进制兼容性。下图清晰展示了这种结构。

图片.png

nginx 使用 C 语言开发,C/C++ 构建工具众多,如手写 Makefile, GNU Autoconf, cmake 等,一些项目甚至专门为自己开发了构建工具,如 boost 库等。nginx 使用哪种构建工具呢?很遗憾,最后一种,自己开发。nginx 使用 shell 脚本维护了一套自动生成 Makefile 的构建脚本,类似简化定制版的 Autoconf 。构建脚本位于代码库 auto/ 目录下,C 源码则位于 src/ 目录下。

nginx 构建脚本同时也用来编译附加模块。

显然,在 nginx 模块中可以自由使用 nginx 主体代码提供的 API 。需要注意的是, 构建时的 nginx 版本必须与运行时的 nginx 版本精确匹配 ,否则 nginx 将拒绝加载。这大概是 nginx 作者懒得精心维护 API 二进制兼容性。不过 模块源码通常是兼容的 ,与不同版本 nginx 源码一起编译即可得到对应版本的动态模块 so 文件。

开发环境

nginx 所需开发环境非常简单,我使用 Ubuntu 18.04 ,使用下列命令即可安装所需最小依赖。

sudo apt-get update
sudo apt-get install build-essential libpcre3-dev zlib1g-dev -y

接下来确定目标 nginx 版本,可使用 nginx -v 查看 nginx 版本,如 Ubuntu 18.04 自带 nginx 版本为 1.14.0 。

$ nginx -v
nginx version: nginx/1.14.0 (Ubuntu)

获取目标 nginx 版本源码,可从 github 拉取。使用 -b 指定拉取版本,--depth 1 表示仅拉取 1 个提交,不要提交历史,这样可以快速完成拉取。

git clone -b release-1.14.0 --depth 1 https://github.com/nginx/nginx.git

在 nginx 代码仓库目录下执行如下命令即可构建生成 nginx 可执行文件。

auto/configure && make
  • auto/configure 脚本检查开发环境和所需依赖,生成 Makefile 脚本,如果有报错按提示修复后重试即可。
  • make 命令使用 Makefile 构建生成 nginx 可执行文件。
  • 默认在代码仓库目录下新建一个名为 objs/ 的目录作为构建目录,构建脚本自动生成的相关文件和最终编译生成的 nginx 可执行文件也在该目录下。

测试运行刚刚生成的 objs/nginx 可执行文件,结果如下。

$ objs/nginx -v
nginx version: nginx/1.14.0

至此,最简 nginx 开发环境准备就绪。

注意: 此 nginx 版本仅用最小依赖和最简配置构建,仅供开发测试动态模块时使用,不可替代生产环境的 nginx 版本。

源码配置与目录结构

模块源码在独立的文件夹下维护 (又称之为插件 addon)。模块源码目录下需提供一个名为 config 的 shell 配置脚本,提供模块信息。nginx 构建脚本将 ngx_addon_dir 变量设置为模块源码路径,并执行 config 脚本获取模块信息。

在 nginx 代码仓库旁边新建一个名为 nginx-hello-module 的模块文件夹,创建一个 config 脚本文件和一个 C 语言源码文件 hello_module.c,即得到一个最简单的模块示例,目录结构如下。

nginx/       # nginx 代码仓库
├── auto/    # nginx 构建脚本目录
└── src/     # nginx 源码目录, 其他文件夹暂未列出。
nginx-hello-module/    # 模块源码目录
├── config             # 模块配置脚本, shell 脚本
└── hello_module.c     # 模块源码文件

编写 config 配置脚本内容如下:

# vim: set ft=sh et:
ngx_addon_name=ngx_http_hello_module

ngx_module_type=HTTP
ngx_module_name="$ngx_addon_name"
ngx_module_srcs="$ngx_addon_dir/hello_module.c"

. auto/module
  • 插件名 ngx_addon_name 和模块名 ngx_module_name 设置为 ngx_http_hello_module 。
  • 模块类型 ngx_module_type 设置为 HTTP 。
  • 源码文件列表 ngx_module_srcs 设置为 $ngx_addon_dir/hello_module.c。注意: 源码路径必须添加 $ngx_addon_dir/ 前缀,构建脚本才能正确找到源码文件。
  • 语句 . auto/module 调用 nginx 提供的模块配置脚本,这条语句固定添加到 config 文件最后。

模块代码开发我们稍后再说,现在可以先建一个空源码文件 hello_module.c 。

在 nginx 代码仓库下执行如下命令,增加配置上述 nginx-hello-module 模块。

auto/configure --add-dynamic-module=../nginx-hello-module/

在 nginx 代码仓库下执行如下命令编译模块。

make modules

竟然编译成功了!得到动态模块文件 objs/ngx_http_hello_module.so 。但此时模块还不可用 (尝试加载此模块将报错),因为我们还没有写任何代码。

一个空模块

我们知道,一个 C 程序的入口是 main() 函数。而一个 nginx 动态模块的入口是一个 ngx_module_t 对象,其结构定义如下。

typedef struct ngx_
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值