您的位置:首页 > 运维架构 > Nginx

OpenResty(nginx+lua) 入门

2015-10-07 21:31 716 查看
OpenResty 官网:http://openresty.org/

OpenResty 是一个nginx和它的各种三方模块的一个打包而成的软件平台。最重要的一点是它将lua/luajit打包了进来,使得我们可以使用lua脚本来进行web的开发。有了lua,我们可以借助于nginx的异步非阻塞的功能,达到使用 lua 异步并发访问后端的 MySQL, PostgreSQL, Memcached, Redis等等服务。特别是特有的 ngx.location.capture_multi 功能让人印象深刻,其可以达到极大的减少浏览器的http连接数量,并且可以异步并发的访问后台 Java/PHP/Python 等等接口。OpenResty 架构的web可以轻松超越Node.js的性能,并且对后端语言没有限制,你可以使用Java/PHP/Python等等各种语言。OpenResty(nginx+lua)可以替代node.js的前端渲染的功能。

OpenResty (aka. ngx_openresty) is a full-fledged web application server by bundling the standard Nginx core, lots of 3rd-party Nginx modules, as well as most of their external dependencies.

By taking advantage of various well-designed Nginx modules, OpenResty
effectively turns the nginx server into a powerful web app server, in
which the web developers can use the Lua programming language to script
various existing nginx C modules and Lua modules and construct extremely
high-performance web applications that are capable to handle 10K+
connections.

OpenResty aims to run your server-side web app
completely in the Nginx server, leveraging Nginx's event model to do
non-blocking I/O not only with the HTTP clients, but also with remote
backends like MySQL, PostgreSQL, Memcached, and Redis.

1. 安装OpenResty

先安装依赖:yum install readline-devel pcre-devel openssl-devel gcc

解压: tar zxvf ngx_openresty-1.9.3.1.tar.gz

建立一个软连接:ln -s ngx_openresty-1.9.3.1 openresty

进入目录:cd openresty

编译:

./configure \
--with-cc-opt="-I/usr/local/include" \
--with-ld-opt="-L/usr/local/lib" \
--prefix=/opt/openresty

... ...
Configuration summary
+ using system PCRE library
+ using system OpenSSL library
+ md5: using OpenSSL library
+ sha1: using OpenSSL library
+ using system zlib library

nginx path prefix: "/opt/openresty/nginx"
nginx binary file: "/opt/openresty/nginx/sbin/nginx"
nginx configuration prefix: "/opt/openresty/nginx/conf"
nginx configuration file: "/opt/openresty/nginx/conf/nginx.conf"
nginx pid file: "/opt/openresty/nginx/logs/nginx.pid"
nginx error log file: "/opt/openresty/nginx/logs/error.log"
nginx http access log file: "/opt/openresty/nginx/logs/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"


其中 --prefix=/opt/openresty 指定了安装目录,不指定的话默认会安装到 /usr/local/openresty 目录下。


编译安装: make && make install

[root@localhost src]# cd /opt/openresty/
[root@localhost openresty]# ls
bin  luajit  lualib  nginx


可以看到 /opt/openresty 目录下四个文件夹,其中包括了 luajit,nginx。

启动openresty: /opt/openresty/nginx/sbin/nginx -c /opt/openresty/nginx/conf/nginx.conf -p /opt/openresty/nginx/

[root@localhost src]# ps -elf|grep nginx
1 S root      2076     1  0  80   0 - 34999 -      21:24 ?        00:00:00 nginx: master process /opt/openresty/nginx/sbin/nginx -c /opt/openresty/nginx/conf/nginx.conf -p /opt/openresty/nginx/
5 S nobody    2077  2076  0  80   0 - 35045 -      21:24 ?        00:00:00 nginx: worker process
0 S root      2079  1678  0  80   0 -  1088 -      21:24 pts/1    00:00:00 grep nginx


验证可以访问: curl 127.0.0.1

2. content_by_lua 和 content_by_lua_file

nginx 如何嵌入 lua 脚本。方法就是在nginx的配置文件nginx.conf 中使用 content_by_lua 或者 cotent_by_lua_file 指令:

1) content_by_lua 一般在很简单的lua脚本时使用:

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


访问 http://localhost/lua 可以看到输出到页面的 hello, world.

2)cotent_by_lua_file 适应于复杂的 lua 脚本,专门放入一个文件中:

location /lua2 {
#lua_code_cache off;
content_by_lua_file lua/hello.lua;
}


路径相对于 /opt/openresty/nginx

[root@localhost lua]# pwd
/opt/openresty/nginx/lua
[root@localhost lua]# cat hello.lua
ngx.say('hello ngx_lua!!!!');


本例子中 hello.lua 只包含一句: ngx.say('hello ngx_lua!!!!');

访问 /lua2 :

[root@localhost lua]# curl localhost/lua
hello ngx_lua!!!!


可以看到访问成功。

在 nginx.conf 文件的 server {.. ...} 中加入 lua_code_cache off; 可以方便调试lua脚本,修改lua脚本之后,不需要 reload nginx.

openresty 中的 nginx 嵌入 luajit 的原理:

[root@localhost lua]# cat cache_lock.lua
local redis = require "resty.redis"
local red = redis:new()
local resty_lock = require "resty.lock"
local ngx_cache = ngx.shared.ngx_cache

function set_to_cache(key, value, exptime)
if not exptime then
exptime = 0
end
local succ, err, forcible = ngx_cache:set(key, value, exptime)
return succ
end

function get_from_cache(key)
local ngx_cache = ngx.shared.ngx_cache;
local value = ngx_cache:get(key)
if not value then       -- cache miss
local lock = resty_lock:new("cache_lock")
local elapsed, err = lock:lock(key)
if not elapsed then
return fail("failed to acquire the lock: ", err)
end

value = get_from_redis(key)
if not value then
local ok, err = lock:unlock()
if not ok then
return fail("failed to unlock: ", err)
end
ngx.say("no value found")
return
end

local ok, err = ngx_cache:set(key, value, 1)
if not ok then
local ok, err = lock:unlock()
if not ok then
return fail("failed to unlock: ", err)
end
return faile("failed to update ngx_cache: ", err)
end

local ok, err = lock:unlock()
if not ok then
return faile("failed to unlock: ", err)
end

return value
end

ngx.say("get from cache.")
return value
end

function get_from_redis(key)
red:set_timeout(1000)

local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.say("failed to connect: ", err)
return
end

local res, err = red:get(key)
if not res then
ngx.say("failed to get doy: ", err)
return ngx.null
end

ngx.say("get from redis.")
return res
end

function set_to_redis(key, value)
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.say("failed to connect: ", err)
return
end

local ok, err = red:set(key, value)
if not ok then
ngx.say("failed to set to redis: ", err)
return
end
return ok
end

set_to_redis('dog', "Bob")
local rs = get_from_cache('dog')
ngx.say(rs)


View Code
测试:

[root@localhost lua]# curl localhost/cache_lock
get from cache.
Bob
[root@localhost lua]# curl localhost/cache_lock
get from cache.
Bob


7. openresty 执行阶段

nginx的执行阶段分成了很多个阶段,所以第三方模块就可以在某个适当的阶段加入一些处理。openresty进行了简化成了7个阶段:



7个阶段的执行顺序如下:

set_by_lua: 流程分支判断,判断变量初始哈

rewrite_by_lua: 用lua脚本实现nginx rewrite

access_by_lua: ip准入,是否能合法性访问,防火墙

content_by_lua: 内存生成

header_filter_by_lua:过滤http头信息,增加头信息

body_filter_by_lua: 内容大小写,内容加密

log_by_lua: 本地/远程记录日志

但是其实我们可以只用 content_by_lua,所有功能都在该阶段完成,也是可以的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: