欢迎来到站长天空!

其它服务器

当前位置: 主页 > 服务器 > 其它服务器

nginx 集成lua操作mysql的过程解析

时间:2025-12-23 17:30:02|栏目:其它服务器|点击:

目录
  • 前言
  • 实现思路
  • ngx_lua模块概念
  • OpenRestry安装步骤
    • 1、下载OpenRestry
    • 2、解压缩文件
    • 3、进入OpenResty目录执行配置
    • 4、 执行命令:make && make install
    • 5、进入OpenResty的目录配置nginx
    • 6、启动nginx并测试
  • ngx_lua常用指令
    • 代码实现
      • lua操作redis
        • lua-resty-redis环境准备
          • lua-resty-redis常用API
            • ngx_lua操作Mysql
              • lua-resty-mysql API说明

                前言

                lua是一夸小巧,灵活且高效的脚本语言,用标准C语言编写并以源代码形式开发,在很多业务场景下配合适当的设计,可以带来意想不到的效果;

                举个常见的例子,现在几乎很多公司都会用到nginx作为代理服务器,假如现在有这么个需求,需要做黑名单过滤,或者在网关这一层做流控,这该怎么做呢?

                实现思路

                • 直接在nginx做配置黑名单,通过编写逻辑块实现;
                • 在服务端(Java)中编写过滤器,在过滤器中统一拦截;
                • 在服务端(Java)中编写拦截器,在拦截器中统一拦截;

                这里列举了3种实现的思路,至于实现方案,可能还有更多,但是我们想想,在nginx中编写逻辑块貌似不是很多人擅长的;在代码层面做不是不可以,而是这样一来,在涉及到高并发的业务高峰期,这必然会对后端服务造成较大的压力,那么还有没有其他更好的处理办法呢?

                这就是要说的lua,即nginx作为网关仍然作为代理服务器,由于nginx可以集成lua,于是使用lua进行配合,来完成上面的业务实现的设计;

                ngx_lua模块概念

                • ngx_lua模块由淘宝技术团队开发,通过将lua解释器集成进Nginx;
                • 可采用lua脚本实现业务逻辑,由于lua的紧凑、快速以及内建协程,所以在保证高并发服务能力的同时极大地降低了业务逻辑实现成本;
                • OpenRestry

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

                简单来说,直接安装并使用OpenRestry,就可以达到同时使用Nginx与Lua的效果,同时基于OpenRestry,还可以在内部操作其他中间件,比如mysql,redis,kafka等,这样就使得业务架构在设计上具备了更大的灵活性;

                OpenRestry安装步骤

                1、下载OpenRestry

                wget https://openresty.org/download/openresty-1.15.8.2.tar.gz

                2、解压缩文件

                tar -zxf openresty-1.15.8.2.tar.gz

                3、进入OpenResty目录执行配置

                这一步有点类似于nginx的源码安装,进行相关的环境变量的配置,这里直接使用默认的就好;

                ./configure

                nginx 集成lua操作mysql的过程解析

                nginx 集成lua操作mysql的过程解析

                4、 执行命令:make && make install

                nginx 集成lua操作mysql的过程解析

                5、进入OpenResty的目录配置nginx

                nginx 集成lua操作mysql的过程解析

                进入nginx目录,可以看到里面的目录和nginx自身安装完毕后的配置几乎一样

                nginx 集成lua操作mysql的过程解析

                进入conf,找到nginx.conf配置文件,添加如下内容:

                location /lua { 
                    default_type 'text/html'; 
                    content_by_lua 'ngx.say(" 

                hello,openRestry lua

                ")'; }

                nginx 集成lua操作mysql的过程解析

                6、启动nginx并测试

                进入nginx的sbin目录下启动nginx

                nginx 集成lua操作mysql的过程解析

                启动完成后,浏览器访问下服务器即可,可以看到nginx本身服务已启动

                nginx 集成lua操作mysql的过程解析

                然后访问上面配置的lua地址,可以看到也能够正常的访问到,说明openrestry的模块已经安装完毕

                nginx 集成lua操作mysql的过程解析

                ngx_lua常用指令

                使用Lua编写Nginx脚本的基本构建块是指令,指令用于指定何时运行用户Lua代码以及如何使用结果,下面针对一些常用的指令做简单的说明

                1、init_by_lua*

                该指令在每次Nginx重新加载配置时执行,用来完成一些耗时操作模块加载,或初始化一些全局配置

                2、init_worker_by_lua*

                该指令用于启动一些定时任务,如心跳检查、定时拉取服务器配置等

                3、set_by_lua*

                该指令只要用来给变量赋值,这个指令一次只能返回一个值,并将结果 值给Nginx中指定变量

                4、rewrite_by_lua*

                用于执行内部URL重写或者外部重定向,典型的如伪静态化URL重 写,本阶段在rewrite处理阶段的最后默认执行(和nginx自身的rewrite功能有类似的地方)

                5、access_by_lua*

                该指令用于访问控制,例如,只允许内网IP访问

                6、content_by_lua*

                该指令是使用最多的指令,大部分任务是在这个阶段完成的,其他过程往往为这个阶段准备数据,正式处理往往都在本阶段执行

                7、header_filter_by_lua*

                用于设置应答消息的头部信息

                8、body_filter_by_lua*

                该指令对响应数据进行过滤,如截断、替换

                9、log_by_lua*

                该指令用于log请求处理阶段,用Lua代码处理日志,但并不替换原有 log处理

                10、balancer_by_lua*

                该指令主要作用是用来实现上游服务器的负载均衡器算法

                11、ssl_certificate_by_*

                该指令作用在Nginx和下游服务开始一个SSL握手操作时将允许本配置项的Lua代码

                一个使用指令的需求

                接下来针对上面提到的各种指令,来做一个简单的需求

                nginx接收到请求后,根据参数中gender传入的值,如果gender传入的是1 则在页面上展示 “先生” , 如果gender传入的是0,则在页面上展示“女士”

                代码实现

                注意:使用指令编写的基本步骤是,在nginx.conf模块中,自定义localtion块中编写lua的相关代码即可

                location /getByGender {
                          default_type 'text/html';
                          set_by_lua $param "
                
                                local uri_args = ngx.req.get_uri_args()
                                local gender = uri_args['gender']
                                local name = uri_args['name']
                                if gender =='1' then
                                       return name..':先生'
                                elseif gender=='0' then
                                       return name..':女士'
                                else
                                       return name
                                end
                          ";
                          charset utf-8;
                          return 200 $param;
                 }
                

                然后启动nginx做一下测试

                1)访问服务,不携带任何参数

                这时候无任何返回信息

                nginx 集成lua操作mysql的过程解析

                2)访问服务,携带name参数

                nginx 集成lua操作mysql的过程解析

                3)访问服务,携带name和gender参数

                nginx 集成lua操作mysql的过程解析

                更多的指令可以参照此类方式编写,但是前提需要掌握一点lua的基本语法

                lua操作redis

                Redis在系统中经常作为数据缓存、内存数据库使用,在各类互联网项目中扮演着非常重要的作用;

                Lua-resty-redis库是OpenResty提供的一个操作Redis的接口库,可根据自己的业务情况做一些逻辑处理,适合做复杂的业务逻辑。所以下面将以Lua-resty-redis来进行说明。

                lua-resty-redis环境准备

                1、提前安装好redis并启动服务

                nginx 集成lua操作mysql的过程解析

                2、测试下redis客户端

                nginx 集成lua操作mysql的过程解析

                lua-resty-redis提供了访问Redis的详细API,包括创建对接、连 接、操作、数据处理等。这些API基本上与Redis的操作是对应起来的

                lua-resty-redis常用API

                1、lua中导入redis依赖

                redis = require "resty.redis"

                2、new,创建一个Redis对象

                redis,err = redis:new()

                3、创建redis连接

                • ok:连接成功返回 1,连接失败返回nil;
                • err:返回对应的错误信息;

                ok,err=redis:connect(host,port[,options_table])

                4、设置请求操作Redis的超时时间

                redis:set_timeout(time)

                5、close,关闭连接

                • 关闭当前连接,成功返回1;
                • 失败返回nil和错误信息;

                ok,err = redis:close()

                补充说明:

                在lua-resty-redis中,所有的Redis命令都有自己的方法;方法名字和命令名字相同,只是全部为小写;

                具体实现效果展示

                在nginx.conf模块下,添加如下的location内容

                location /redis {
                    default_type "text/html";
                    content_by_lua_block {
                        local redis = require "resty.redis"     -- 引入 Redis
                        local redisObj = redis:new()            --创建Redis对象
                        redisObj:set_timeout(3000)              --设置超时数据为3s
                        local ok,err = redisObj:connect("IP",6379)    --设置redis连接信息
                        if not ok then                          --判断是否连接成功
                            ngx.say("failed to connection redis",err)
                            return
                        end
                        ok,err = redisObj:set("username","TOM")     --存入 数据
                        if not ok then                              --判断是否存入成功
                            ngx.say("failed to set username",err)
                            return
                        end
                        local res,err = redisObj:get("username")    --从 redis中获取数据
                        ngx.say(res) --将数据写会消息体中
                        redisObj:close()
                    }
                }

                重启nginx,进行测试,直接在浏览器访问一下如下地址,可以看到数据成功写入到redis

                nginx 集成lua操作mysql的过程解析
                nginx 集成lua操作mysql的过程解析

                ngx_lua操作Mysql

                MySQL是一个使用广泛的关系型数据库。在ngx_lua中,MySQL有两种访问模式,分别是

                • 用ngx_lua模块和lua-resty-mysql模块: 这两个模块是安装OpenResty时默认安装的;
                • 使用drizzle_nginx_module(HttpDrizzleModule)模块:需要单独

                安装,这个库现不在OpenResty中

                lua-resty-mysql

                lua-resty-mysql是OpenResty开发的模块,使用灵活、功能强大,适合复杂的业务场景,同时支持存储过程访问;

                lua-resty-mysql实现数据库查询

                1、准备好mysql服务

                nginx 集成lua操作mysql的过程解析

                2、提前创建一张表

                CREATE TABLE `users` (
                  `id` int(10) NOT NULL AUTO_INCREMENT,
                  `username` varchar(255) DEFAULT NULL,
                  `birthday` date DEFAULT NULL,
                  `salary` double(10,2) DEFAULT NULL,
                  PRIMARY KEY (`id`)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

                并提前准备几条数据

                INSERT INTO `mydb`.`users` (`id`, `username`, `birthday`, `salary`) VALUES ('1', 'xiaowang', '1991-03-15', '9000.00');
                INSERT INTO `mydb`.`users` (`id`, `username`, `birthday`, `salary`) VALUES ('2', 'xiaoma', '1992-07-15', '8000.00');

                lua-resty-mysql API说明

                1、引入"resty.mysql"模块

                local mysql = require "resty.mysql"

                2、创建MySQL连接对象

                遇到错误时,db为nil,err为错误描 述信息

                db,err = mysql:new()

                3、创建连接对象

                ok,err=db:connect(options)

                options是一个参数的 Lua表结构,里面包含数据库连接的相关信息

                • host:服务器主机名或IP地址
                • port:服务器监听端口,默认为3306
                • user:登录的用户名
                • password:登录密码
                • database:使用的数据库名

                4、设置子请求的超时时间(ms)

                包括connect方法

                db:set_timeout(time)

                5、关闭当前MySQL连接并返回状态

                如果成功,则返回1;如果出现任 何错误,则将返回nil和错误描述

                db:close()

                6、异步向远程MySQL发送一个查询

                如果成功则返回成功发送的字节 数;如果错误,则返回nil和错误描述

                bytes,err=db:send_query(sql)

                7、从MySQL服务器返回结果中读取一行数据

                • res返回一个描述OK包 或结果集包的Lua表
                • rows指定返回结果集的最大值,默认为4
                • 如果是查询,则返回一个容纳多行的数组。每行是一个数据列的 key-value对
                res, err, errcode, sqlstate = db:read_result() res, err, errcode, sqlstate = db:read_result(rows)

                返回结果类似下面这样

                { 
                {id=1,username="TOM",birthday="1988-11- 11",salary=10000.0}, {id=2,username="JERRY",birthday="1989-11- 11",salary=20000.0} 
                }

                如果是增删改,则返回类似如下数据

                { 
                	insert_id = 0, 
                	server_status=2, 
                	warning_count=1, 
                	affected_rows=2, 
                	message=nil 
                }

                返回值说明:

                • res:操作的结果集
                • err:错误信息
                • errcode:MySQL的错误码,比如1064
                • sqlstate:返回由5个字符组成的标准SQL错误码,比如 42000

                具体操作案例

                将下面的内容添加到server块,然后重启nginx

                location /mysql {
                     content_by_lua_block{
                		default_type "text/html";
                        local mysql = require "resty.mysql" 
                        local db = mysql:new() 
                        local ok,err = db:connect{ 
                            host="127.0.0.1", 
                            port=3306,
                            user="root", 
                            password="123456", 
                            database="mydb"
                        } 
                            db:set_timeout(3000) 
                            db:send_query("select * from users where id =1") 
                            local res,err,errcode,sqlstate = db:read_result() 
                            ngx.say(res[1].id..","..res[1].username..","..res[1]. birthday..","..res[1].salary)
                            db:close()
                    } 
                }
                

                可以看到,通过访问mysql这个路径,成功查询到数据库中ID为1的这条数据

                nginx 集成lua操作mysql的过程解析

                使用cjson对查询结果进行格式化

                从上面的返回结果来看,这种形式的返回数据在解析的时候其实并不是很友好,于是可以使用lua-cjson处理查询结果

                使用步骤

                步骤一:引入cjson

                local cjson = require “cjson”

                步骤二:调用cjson的encode方法进行类型转换

                cjson.encode(res)

                下面对上面程序模块做简单的改造

                location /mysql-cjson {
                		default_type "text/html";
                     content_by_lua_block{
                     	local cjson = require "cjson"
                        local mysql = require "resty.mysql" 
                        local db = mysql:new() 
                        local ok,err = db:connect{ 
                            host="127.0.0.1", 
                            port=3306,
                            user="root", 
                            password="123456", 
                            database="mydb"
                        } 
                            db:set_timeout(3000) 
                            db:send_query("select * from users") 
                            local res,err,errcode,sqlstate = db:read_result() 
                            ngx.say(cjson.encode(res))
                            for i,v in ipairs(res) do
                                ngx.say(v.id..","..v.username..","..v.birthday..",".. v.salary)
                            end
                            db:close()
                    } 
                }
                

                然后再次进行测试,这时候就以json的格式对数据进行了展现

                nginx 集成lua操作mysql的过程解析

                增删改操作

                location /mysql-cjson {
                		default_type "text/html";
                     content_by_lua_block{
                     	local cjson = require "cjson"
                        local mysql = require "resty.mysql" 
                
                        local db = mysql:new() 
                
                        local ok,err = db:connect{ 
                            host="127.0.0.1", 
                            port=3306,
                            user="root", 
                            password="123456", 
                            database="mydb"
                        } 
                            db:set_timeout(3000) 
                            -- 查询操作
                            db:send_query("select * from users where id=1") 
                			-- 插入数据
                			--local res,err,errcode,sqlstate = db:query("insert into users(id,username,birthday,salary) values(3,'lifei','1995-10-17',3000)")
                			-- 修改数据
                			--local res,err,errcode,sqlstate = db:query("update users set username='lisi' where id = 1")
                			-- 删除数据
                			--local res,err,errcode,sqlstate = db:query("delete from users where id = 2")
                            db:close()
                    } 
                }
                

                上一篇:linux怎么查看tomcat是否启动成功

                栏    目:其它服务器

                下一篇:Nginx将http转换成https的详细过程

                本文标题:nginx 集成lua操作mysql的过程解析

                本文地址:https://zz.feitang.co/server/32956.html

                广告投放 | 联系我们 | 版权申明

                申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

                如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

                联系QQ:257218569 | 邮箱:257218569@qq.com

                Copyright © 2018-2025 站长天空 版权所有 Powered by EyouCms冀ICP备14023439号