首頁  >  文章  >  運維  >  nginx怎麼整合lua操作mysql

nginx怎麼整合lua操作mysql

WBOY
WBOY轉載
2023-05-16 22:43:111180瀏覽

實作想法

  • 直接在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 &#39;ngx.say(" <h2>hello,openRestry lua</h2>")&#39;; 
}

nginx怎麼整合lua操作mysql

#6、啟動nginx並測試

進入nginx的sbin目錄下啟動nginx

nginx怎麼整合lua操作mysql

啟動完成後,瀏覽器造訪下伺服器即可,可以看到nginx本身服務已啟動

nginx怎麼整合lua操作mysql

存取已配置的Lua位址後,可以發現可以正常訪問,這表明OpenResty模組已經成功安裝

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 &#39;text/html&#39;;
          set_by_lua $param "

                local uri_args = ngx.req.get_uri_args()
                local gender = uri_args[&#39;gender&#39;]
                local name = uri_args[&#39;name&#39;]
                if gender ==&#39;1&#39; then
                       return name..&#39;:先生&#39;
                elseif gender==&#39;0&#39; then
                       return name..&#39;:女士&#39;
                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 (&#39;1&#39;, &#39;xiaowang&#39;, &#39;1991-03-15&#39;, &#39;9000.00&#39;);
INSERT INTO `mydb`.`users` (`id`, `username`, `birthday`, `salary`) VALUES (&#39;2&#39;, &#39;xiaoma&#39;, &#39;1992-07-15&#39;, &#39;8000.00&#39;);

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()
    } 
}

以上是nginx怎麼整合lua操作mysql的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除