IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

Nginx与Lua

火丁笔记 2012-09-02 20:32:58 累计浏览 5,670 次
本机暂存

    火云邪神语录:天下武功,无坚不破,唯快不破!Nginx的看家本领就是速度,Lua的拿手好戏亦是速度,这两者的结合在速度上无疑有基因上的优势。

    最先将Nginx,Lua组合到一起的是OpenResty,它有一个ngx_lua模块,将Lua嵌入到了Nginx里面;随后Tengine也包含了ngx_lua模块。至于二者的区别:OpenResty是Nginx的Bundle;而Tengine则是Nginx的Fork。值得一提的是,OpenResty和Tengine均是国人自己创建的项目,前者主要由春哥晓哲开发,后者主要由淘宝打理。

    至于OpenResty和Tengine孰优孰劣,留给大家自己判断,如下资料可供参考:

  • ngx_openresty: an Nginx ecosystem glued by Lua
  • 淘宝网Nginx应用、定制与开发实战
  •     推荐看看春哥在Tech-Club上关于『由Lua粘合的Nginx生态环境』的演讲实录,有料!

    安装

        需要最新版的NginxLuaJITngx_devel_kitngx_lua等安装文件。

        安装Lua或者LuaJIT都是可以的,但是出于效率的考虑,推荐安装LuaJIT。

    shell> wget http://luajit.org/download/LuaJIT-.tar.gz
    shell> tar zxvf LuaJIT-.tar.gz
    shell> cd LuaJIT-
    shell> make
    shell> make install

        因为安装在缺省路径,所以LuaJIT对应的lib,include均在/usr/local目录里。

    shell> export LUAJIT_LIB=/usr/local/lib
    shell> export LUAJIT_INC=/usr/local/include/luajit-

        下面就可以编译Nginx了:

    shell> wget http://nginx.org/download/nginx-.tar.gz
    shell> tar zxvf nginx-.tar.gz
    shell> cd nginx-
    shell> ./configure
        --add-module=/path/to/ngx_lua \\
        --add-module=/path/to/ngx_devel_kit
    shell> make
    shell> make install

        试着启动一下Nginx看看,如果你运气不好的话,可以会遇到如下错误:

        cannot open shared object file: No such file or directory

        这是神马情况?可以用ldd命令来看看:

    shell> ldd /path/to/nginx
    libluajit-.so => not found

        此类问题通常使用ldconfig命令就能解决:

    shell> echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
    shell> ldconfig

        再试着启动Nginx看看,应该就OK了。

    应用

        我们先用一个简单的程序来暖暖场:把下面的代码加入到Nginx的配置文件nginx.conf,并重启Nginx,然后浏览,就能看到效果了。

    location /test {
        set $test "hello, world.";
        content_by_lua \'
            ngx.header.content_type = "text/plain";
            ngx.say(ngx.var.test);
        \';
    }

        在深入学习ngx_lua之前,建议大家仔细阅读一遍春哥写的Nginx教程

        这里我就说关键的:Nginx配置文件所使用的语言本质上是『声明性的』,而非『过程性的』。Nginx处理请求的时候,指令的执行并不是由定义指令时的物理顺序来决定的,而是取决于指令所属的阶段,Nginx常用的阶段按先后顺序有:rewrite阶段,access阶段,content阶段等等。演示代码中的set指令属于rewrite阶段,content_by_lua指令属于content阶段,如果试着把两条指令的顺序交换一下,会发现程序依然能够正常运行。

        下面我们尝试结合Redis写个更实战一点的例子。

        首先,我们需要创建一个Redis配置文件config.json,内容如下:

    {
        "host": "",
        "port": ""
    }

        然后,我们创建一个解析配置文件的脚本init.lua,其中用到了Lua CJSON模块:

    local cjson = require "cjson";
    
    local config = ngx.shared.config;
    
    local file = io.open("config.json", "r");
    local content = cjson.decode(file:read("*all"));
    file:close();
    
    for name, value in pairs(content) do
        config:set(name, value);
    end

        说明:代码里用到了共享内存,这样就不必每次请求都解析一遍配置文件了。

        接着,我们创建一个内容脚本content.lua,用到了Resty Redis模块:

    local redis = require "resty.redis";
    
    local config = ngx.shared.config;
    
    local instance = redis:new();
    
    local host = config:get("host");
    local port = config:get("port");
    
    local ok, err = instance:connect(host, port);
    if not ok then
        ngx.log(ngx.ERR, err);
        ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE);
    end
    
    local res, err = instance:set("name", "laowang");
    if not res then
        ngx.log(ngx.ERR, err);
        ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE);
    end
    
    local res, err = instance:get("name");
    if not res then
        ngx.log(ngx.ERR, err);
        ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE);
    end
    
    instance:close();
    
    ngx.say("name: ", res);

        说明:建议把Resty Redis模块放到vendor目录下,稍后在Nginx.conf中统一设置。

        最后,我们需要在Nginx配置文件里设置一下:

    lua_shared_dict config 1m;
    lua_package_path "/path/to/vendor/?.lua;;";
    
    server {
        lua_code_cache off;
    
        location /test {
            init_by_lua_file    /path/to/init.lua;
            content_by_lua_file /path/to/content.lua;
        }
    }

        说明:为了方便调试,我关闭了lua_code_cache,如果是生产环境,应该开启它。

        …

        我最近参与的一个项目,提供了一些用于Web轮询的接口,都是用Nginx+Lua实现的,虽然总共只有十几台服务器,但是每天可以提供接近几十亿次的请求量,贼拉拉的强。

    同分类推荐文章

    1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
    2. Go 实验特性详解 (2026-06-21 10:05:27)
    3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

    查看更多 后端 文章 →

    建议继续学习

    1. 配置Nginx+uwsgi更方便地部署python应用 (累计阅读 107,164)
    2. 搜狐闪电邮箱的 Nginx/Postfix 使用模式 (累计阅读 33,895)
    3. 记录一个软中断问题 (累计阅读 16,954)
    4. 解析nginx负载均衡 (累计阅读 16,622)
    5. server日志的路径分析 (累计阅读 11,239)
    6. Nginx模块开发入门 (累计阅读 11,169)
    7. 检查nginx配置,重载配置以及重启的方法 (累计阅读 10,896)
    8. Cacti 添加 Nginx 监控 (累计阅读 10,641)
    9. fsockopen 异步处理 (累计阅读 10,344)
    10. 使用Squid缓存视频 (累计阅读 10,339)