OpenResty安装使用

OpenResty安装使用

在Nginx新版本中没有直接提供Lua模块的集成,Lua脚本模块已经作为第三方集成模块中去了,查看Nginx博客地址可知,集成到OpenResty中,OpenResty由主要国人章亦春维护的项目。

OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

充分利用 Nginx的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。

安装OpenResty

有二进制安装包、源码构建两种方式来安装OpenResty

安装OpenResty

官网提供二进制安装包,以CentOS为例,通过yum命令即可安装。其他系统参考官网

# 添加 openresty 仓库
sudo yum install yum-utils
sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
# 安装OpenResty
sudo yum install openresty
# 安装命令行工具 resty
sudo yum install openresty-resty

构建OpenResty

下载解压
# 安装依赖工具
yum install -y pcre-devel openssl-devel gcc curl
# 下载源码包
wget https://openresty.org/download/openresty-1.15.8.1.tar.gz
# 解压构建并安装
tar -xzvf openresty-1.15.8.1.tar.gz
sudo mv openresty-1.15.8.1 openresty
sudo mv openresty /usr/local
cd openresty/
编译选项

可以通过./configure --help来了解,编译的各种选项,例如

......
--without-http_srcache_module      disable ngx_http_srcache_module
--without-http_lua_module          disable ngx_http_lua_module
--without-http_lua_upstream_module disable ngx_http_lua_upstream_module
--without-http_headers_more_module disable ngx_http_headers_more_module
--without-http_array_var_module    disable ngx_http_array_var_module
--without-http_memc_module         disable ngx_http_memc_module
--without-http_redis2_module       disable ngx_http_redis2_module
--without-http_redis_module        disable ngx_http_redis_module
--without-http_rds_json_module     disable ngx_http_rds_json_module
--without-http_rds_csv_module      disable ngx_http_rds_csv_module
--without-stream_lua_module        disable ngx_stream_lua_module
--without-ngx_devel_kit_module     disable ngx_devel_kit_module
--without-http_ssl_module          disable ngx_http_ssl_module
--without-stream_ssl_module        disable ngx_stream_ssl_module
......

你可以这样来添加和去除你想要选择的模块。

./configure --prefix=/opt/openresty \ #指定编译目录,默认为/usr/local/openresty
            --with-luajit \
            --without-http_redis2_module \
            --with-http_iconv_module \
            --with-http_postgres_module

你也可以使用默认配置

sudo ./configure
编译安装
sudo make
sudo make install

启动OpenResty

实际上openresty使用的是nginx,openresty文件通过链接的形式,连到/usr/local/openresty/nginx/sbin/nginx文件,所以使用openresty与使用nginx并无太大区别。

启动

sudo bin/openresty

关闭

sudo bin/openresty -s stop

测试Lua脚本

编写Lua脚本

cd /usr/local/openresty/
sudo mkdir lua_scripts
cd lua_scripts
sudo vim mydata.lua

往mydata.lua中输入内容

local _M = {}

local data = {
   dog = 5,
   cat = 3,
   pig = 1,
}

function _M.get_age(name)
   return data[name]
end
return _M

调整配置

sudo vim /usr/local/openresty/nginx/conf/nginx_lua.conf

配置内容

worker_processes  1;
events {
    worker_connections 1024;
}

http {
	lua_package_path "/usr/local/openresty/lua_scripts/?.lua;;";
    server {
        listen 8080;
        location /lua {
            default_type text/html;
            content_by_lua_block {
                local mydata = require "mydata"
               ngx.say(mydata.get_age("dog"))
            }
        }
    }
}

启动测试

sudo bin/openresty -c conf/nginx_lua.conf

有人可能在奇怪,为什么配置文件不是nginx/conf/nginx_lua.conf。那是因为使用nginx/conf/nginx_lua.conf路径,发现报错,错误内容告诉我们找不到配置文件,错误信息里面的路径上多了一个nginx目录。

输出内容

curl http://localhost:8080/lua
5

看到输出内容,表示已经安装成功,并且成功的访问了,实现的一个小小的lua脚本。

使用Redis

《nginx_lua_redis.conf》文件:

worker_processes  1;
events {
    worker_connections 1024;
}

http {
    # 设置由set_by_lua, content_by_lua等指定的脚本使用的Lua模块搜索路径。类似java的classPath
    # 路径字符串采用标准的Lua路径形式,;; 可用于代表原始搜索路径。
	lua_package_path "/usr/local/openresty/lua_scripts/?.lua;;";

    # 申请一个名为dogs的10m字典内存,共享在所有工作进程中
    lua_shared_dict dogs 10m;
    
    server {
        listen 8080;
        location /lua {
            default_type text/html;
            lua_code_cache on;
            # mysql只需要替换成mysql_demo.lua脚本即可
            content_by_lua_file redis_demo.lua;
        }
    }
}

《redis_demo.lua》文件:

local function close_redis(red)  
    if not red then  
        return  
    end  
	--释放连接(Redis连接池实现)
    local pool_max_idle_time = 10000 --毫秒  
    local pool_size = 100 --连接池大小  
    local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)  
    if not ok then
        ngx.say("set keepalive error : ", err)
    end 
end  
  
local redis = require("resty.redis")  
  
--创建实例  
local red = redis:new()  
--设置超时(毫秒)  
red:set_timeout(1000)  
--建立连接  
local ip = "127.0.0.1"  
local port = 6379  
local ok, err = red:connect(ip, port)  
if not ok then  
    ngx.say("connect to redis error : ", err)  
    return close_redis(red)  
end  
--调用API进行处理  
ok, err = red:set("msg", "hello world")  
if not ok then  
    ngx.say("set msg error : ", err)  
    return close_redis(red)  
end  
  
--调用API获取数据  
local resp, err = red:get("msg")  
if not resp then  
    ngx.say("get msg error : ", err)  
    return close_redis(red)  
end  
--得到的数据为空处理  
if resp == ngx.null then  
    resp = ''  --比如默认值
end  
ngx.say("msg : ", resp)  
  
close_redis(red) 

使用MySQL

《mysql_demo.lua》文件:

    local function close_db(db)  
        if not db then  
            return  
        end  
        db:close()  
    end  
      
    local mysql = require("resty.mysql")  
    --创建实例  
    local db, err = mysql:new()  
    if not db then  
        ngx.say("new mysql error : ", err)  
        return  
    end  
    --设置超时时间(毫秒)  
    db:set_timeout(1000)  
      
    local props = {  
        host = "127.0.0.1",  
        port = 3306,  
        database = "mysql",  
        user = "root",  
        password = "123456"  
    }  
      
    local res, err, errno, sqlstate = db:connect(props)  
      
    if not res then  
       ngx.say("connect to mysql error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
       return close_db(db)  
    end  
      
    --删除表  
    local drop_table_sql = "drop table if exists test"  
    res, err, errno, sqlstate = db:query(drop_table_sql)  
    if not res then  
       ngx.say("drop table error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
       return close_db(db)  
    end  
      
    --创建表  
    local create_table_sql = "create table test(id int primary key auto_increment, ch varchar(100))"  
    res, err, errno, sqlstate = db:query(create_table_sql)  
    if not res then  
       ngx.say("create table error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
       return close_db(db)  
    end  
      
    --插入  
    local insert_sql = "insert into test (ch) values('hello')"  
    res, err, errno, sqlstate = db:query(insert_sql)  
    if not res then  
       ngx.say("insert error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
       return close_db(db)  
    end  
      
    res, err, errno, sqlstate = db:query(insert_sql)  
      
    ngx.say("insert rows : ", res.affected_rows, " , id : ", res.insert_id, "<br/>")  
      
    --更新  
    local update_sql = "update test set ch = 'hello2' where id =" .. res.insert_id  
    res, err, errno, sqlstate = db:query(update_sql)  
    if not res then  
       ngx.say("update error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
       return close_db(db)  
    end  
      
    ngx.say("update rows : ", res.affected_rows, "<br/>")  
    --查询  
    local select_sql = "select id, ch from test"  
    res, err, errno, sqlstate = db:query(select_sql)  
    if not res then  
       ngx.say("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
       return close_db(db)  
    end  
      
      
    for i, row in ipairs(res) do  
       for name, value in pairs(row) do  
         ngx.say("select row ", i, " : ", name, " = ", value, "<br/>")  
       end  
    end  
      
    ngx.say("<br/>")  
    --防止sql注入  
    local ch_param = ngx.req.get_uri_args()["ch"] or ''  
    --使用ngx.quote_sql_str防止sql注入  
    local query_sql = "select id, ch from test where ch = " .. ngx.quote_sql_str(ch_param)  
    res, err, errno, sqlstate = db:query(query_sql)  
    if not res then  
       ngx.say("select error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
       return close_db(db)  
    end  
      
    for i, row in ipairs(res) do  
       for name, value in pairs(row) do  
         ngx.say("select row ", i, " : ", name, " = ", value, "<br/>")  
       end  
    end  
      
    --删除  
    local delete_sql = "delete from test"  
    res, err, errno, sqlstate = db:query(delete_sql)  
    if not res then  
       ngx.say("delete error : ", err, " , errno : ", errno, " , sqlstate : ", sqlstate)  
       return close_db(db)  
    end  
      
    ngx.say("delete rows : ", res.affected_rows, "<br/>")  
      
    close_db(db)  

《nginx_lua_msyql.conf》文件和上面的nginx_lua_redis.conf差不多,就是替换redis_demo.lua替换为mysql_demo.lua

使用HTTP客户端

OpenResty默认没有提供Http客户端,需要使用第三方提供,从github上搜索相应的客户端,比如lua-resty-http

下载插件

​ 下载lua-resty-http客户端到lualib

cd /usr/local/openresty/lua_scripts  
sudo wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http_headers.lua 
sudo wget https://raw.githubusercontent.com/pintsized/lua-resty-http/master/lib/resty/http.lua

lua脚本

cd /usr/local/openresty/lua_scripts
sudo vim http_demo.lua

输入内容,参考《http_demo.lua》

nginx配置

参考《nginx_lua_redis.conf》文件,在http部分添加谷歌dns解析器,修改对应的lua脚本文件。

resolver 8.8.8.8;

Lua模板渲染器

动态web网页开发是Web开发中一个常见的场景,Lua中也有许多模板引擎,我们通过lua-resty-template来完成动态页面的渲染。

下载lua-resty-template

cd /usr/local/openresty/lua_scripts
wget https://raw.githubusercontent.com/bungle/lua-resty-template/master/lib/resty/template.lua
mkdir /usr/example/lualib/resty/html  
cd /usr/local/openresty/lua_scripts
wget https://raw.githubusercontent.com/bungle/lua-resty-template/master/lib/resty/template/html.lua

使用

lua内容,html_template.lua

local template = require("resty.template")  

local context = {  
    title = "lua模板渲染",  
    name = "hash同学",  
    description = "<script>alert(1);</script>",  
    age = 20,  
    hobby = {"电影", "音乐", "阅读"},  
    score = {语文 = 90, 数学 = 80, 英语 = 70},  
    score2 = {  
        {name = "语文", score = 90},  
        {name = "数学", score = 80},  
        {name = "英语", score = 70},  
    }  
}
template.render("resty_template.html", context)

resty_template.html文件的html内容

<html>
    <head>
        <title>{* titile *}</title>
    </head>
    <body>
        {# 不转义变量输出 #}  
        姓名:{* string.upper(name) *}<br/>  
        {# 转义变量输出 #}  
        简介:{{description}}<br/>
        {# 可以做一些运算 #}  
        年龄: {* age + 1 *}<br/>  
        {# 循环输出 #}  
        爱好:  
        {% for i, v in ipairs(hobby) do %}  
           {% if i > 1 then %},{% end %}  
           {* v *}  
        {% end %}<br/>  

        成绩:  
        {% local i = 1; %}  
        {% for k, v in pairs(score) do %}  
           {% if i > 1 then %},{% end %}  
           {* k *} = {* v *}  
           {% i = i + 1 %}  
        {% end %}<br/>  
        成绩2:  
        {% for i = 1, #score2 do local t = score2[i] %}  
           {% if i > 1 then %},{% end %}  
            {* t.name *} = {* t.score *}  
        {% end %}<br/>  
        {# 中间内容不解析 #}  
        {-raw-}{(file)}{-raw-}  
    </body>
</html>

{* var *}:变量输出;

{{ var }}:变量转义输出;

{% code %}:代码片段;

{# comment #}:注释;

{-raw-}:中间的内容不会解析,作为纯文本输出;

{(include_file)}:包含另一个模板文件

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值