Aldebaran

人生最棒的感觉,就是你做到别人说你做不到的事。

0%

Nginx动态加载模块

三田寺円

前言

从Nginx 1.9.11版本带来一个重要的新功能:动态模块,给我们以后如何使用Nginx带来了巨大的影响。

不过需要我们先在编译 Nginx (./configure)时指定

  • 源码模块:./configure –with-mail=dynamic …
  • 第三方模块 :./configure –add-dynamic-module=…

模块对应的 .so 文件会被存放在 /path/nginx/modules/ 下面,当需要使用模块时,在 nginx.conf 最顶端(main)配置 load_module,指定模块路径。

但是,这时添加模块仍然需要在编译阶段声明,即需要重新编译 Nginx 程序,很多时候,在生产环境是不能随便去更新替换二进制程序的。

因此,在 nginx-1.11.5 编译命令增加了 –with-compat,可以单独编译需要新增的模块,直接动态加载到原有的 nginx 二进制程序,而不用重新编译 nginx!

注意:编译系统模块需要再加上 –add-module 参数, 编译第三方模块需要再加上–add-dynamic-module参数。

官方阐述:

Dynamic modules – NGINX 1.11.5 was a milestone moment in the development of NGINX. It introduced
 the new --with-compat option which allows any module to be compiled and dynamically loaded into a
running NGINX instance of the same version (and an NGINX Plus release based on that version).
There are over 120 modules for NGINX contributed by the open source community, and now you can load
them into our NGINX builds, or those of an OS vendor, without having to compile NGINX from source.
For more information on compiling dynamic modules, see Compiling Dynamic Modules for NGINX Plus.

测试

下面的两个测试例子。

1. 以动态加载模块 nginx-hello-world-module 为例

  • 假设Nginx已经安装完成,且开启–with-compat 参数,并且Nginx版本大于等于nginx-1.11.5。

      $ wget http://nginx.org/download/nginx-1.11.5.tar.gz
      $ tar -xzvf nginx-1.11.5.tar.gz
    
  • 拉取模块源码,开始编译。

      $ git clone https://github.com/perusio/nginx-hello-world-module.git
      $ cd nginx-1.11.5/
      # 编译系统模块使用 --add-module, 编译第三方模块使用--add-dynamic-module。
      $ ./configure --with-compat --add-dynamic-module=../nginx-hello-world-module
      $ make modules
      # 将模块库(.so文件)复制到/etc/nginx/modules:
      $ sudo cp objs/ngx_http_hello_world_module.so /etc/nginx/modules/
    
  • 加载并使用模块,在 nginx.conf 最顶端添加(不在http或stream上下文中):

      load_module modules/ngx_http_hello_world_module.so;
    
  • 测试

    在http上下文中,location使用hello_worldHello World模块提供的指令添加块。对该位置的请求将返回响应hello world。

      server {
          listen 80;
          location / {
              hello_world;
          }
      }
    
      $ nginx -s reload
      $ curl http://localhost/
    

2. 以动态加载模块 lua-nginx-module 为例,展示具体用法。

  • 编译安装 Nginx,这里其实唯一要注意的就是记得带上 –with-compat 开启兼容模式,并且Nginx版本大于等于nginx-1.11.5

  • 下载 lua-nginx-module 源码包,及依赖ngx_devel_kit, 例如:

    以下仅为测试,lua-nginx版本不建议很高,lua-nginx-v0.10.13足够。

      $ wget https://github.com/openresty/lua-nginx-module/archive/v0.10.13.tar.gz -O lua-nginx-v0.10.13.tar.gz
      $ wget https://github.com/simplresty/ngx_devel_kit/archive/v0.3.1.tar.gz -O ngx_devel_kitv-0.3.1.tar.gz
    
      $ tar xf lua-nginx-v0.10.13.tar.gz
      $ tar xf ngx_devel_kitv-0.3.1.tar.gz
    
  • 动态加载

    • 编译安装 .so 文件(需要先安装好 LuaJIT和Lua)

        $ wget http://nginx.org/download/nginx-1.11.5.tar.gz
        $ tar -xzvf nginx-1.11.5.tar.gz
        $ cd ./nginx-1.11.5/
        $ ./configure --with-compat \
            --with-cc-opt='-O0 -I /usr/local/include/luajit-2.0' \
            --with-ld-opt='-Wl,-rpath,/usr/local/lib -lluajit-5.1' \
            --add-dynamic-module=../lua-nginx-module-0.10.13 \
            --add-dynamic-module=../ngx_devel_kit-0.3.1
      
        $ make modules
        # 将模块库(.so文件)复制到/etc/nginx/modules:
        $ cp objs/ndk_http_module.so objs/ngx_http_lua_module.so ../nginx-dy/nginx/modules/
      
  • 配置使用,在 nginx.conf 最顶端添加:

      load_module modules/ndk_http_module.so;
      load_module modules/ngx_http_lua_module.so;
    
  • 完成

      $ nginx -t
    
  • 遇到的坑

    • 编译 Nginx,要带上 –with-compat ,否则运行 Nginx 时,会报 ngx_lua 模块不兼容的错误。
    • 编译 Nginx要使用 –with-ld-opt 指定 PCRE 等依赖组件 lib 安装路径,否则会报动态库链接符号错误。、,例如: –with-ld-opt=’-Wl,-rpath,/usr/local/lib -lluajit-5.1’ 。
    • 需要指定 –with-cc-opt,例如:–with-cc-opt=’-O0 -I /usr/local/include/luajit-2.0’ 。

小结

Nginx 动态加载模块,使增加功能模块变的更加方便与灵活。

参考链接

https://github.com/jinhailang/blog/issues/24

https://www.nginx.com/resources/wiki/extending/converting/#compiling-dynamic

https://www.nginx.com/blog/compiling-dynamic-modules-nginx-plus/