Nginx与Lua
火云邪神语录:天下武功,无坚不破,唯快不破!Nginx的看家本领就是速度,Lua的拿手好戏亦是速度,这两者的结合在速度上无疑有基因上的优势。
最先将Nginx,Lua组合到一起的是OpenResty,它有一个ngx_lua模块,将Lua嵌入到了Nginx里面;随后Tengine也包含了ngx_lua模块。至于二者的区别:OpenResty是Nginx的Bundle;而Tengine则是Nginx的Fork。值得一提的是,OpenResty和Tengine均是国人自己创建的项目,前者主要由春哥和晓哲开发,后者主要由淘宝打理。
至于OpenResty和Tengine孰优孰劣,留给大家自己判断,如下资料可供参考:
推荐看看春哥在Tech-Club上关于『由Lua粘合的Nginx生态环境』的演讲实录,有料!
安装
需要最新版的Nginx,LuaJIT,ngx_devel_kit,ngx_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实现的,虽然总共只有十几台服务器,但是每天可以提供接近几十亿次的请求量,贼拉拉的强。
建议继续学习:
- 配置Nginx+uwsgi更方便地部署python应用 (阅读:105413)
- 搜狐闪电邮箱的 Nginx/Postfix 使用模式 (阅读:32536)
- 解析nginx负载均衡 (阅读:14537)
- Nginx模块开发入门 (阅读:9898)
- 检查nginx配置,重载配置以及重启的方法 (阅读:9115)
- Cacti 添加 Nginx 监控 (阅读:8929)
- Nginx+FastCgi+Php 的工作机制 (阅读:8868)
- nginx的配置文件 (阅读:8842)
- 奇怪的 Nginx 的 upstream timed out 引起响应 502 (阅读:8177)
- 解决IE6从Nginx服务器下载图片不Cache的Bug (阅读:7115)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:老王 来源: 火丁笔记
- 标签: Lua Nginx
- 发布时间:2012-09-02 20:32:58
- [43] android 开发入门
- [42] Oracle MTS模式下 进程地址与会话信
- [40] IOS安全–浅谈关于IOS加固的几种方法
- [38] Go Reflect 性能
- [37] 读书笔记-壹百度:百度十年千倍的29条法则
- [37] 如何拿下简短的域名
- [36] 图书馆的世界纪录
- [35] 【社会化设计】自我(self)部分――欢迎区
- [30] 程序员技术练级攻略
- [29] 视觉调整-设计师 vs. 逻辑