人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動(dòng)態(tài)

nginx?集成lua操作mysql的過(guò)程解析

發(fā)布日期:2022-07-20 19:36 | 文章來(lái)源:站長(zhǎng)之家

lua是一夸小巧,靈活且高效的腳本語(yǔ)言,用標(biāo)準(zhǔn)C語(yǔ)言編寫(xiě)并以源代碼形式開(kāi)發(fā),在很多業(yè)務(wù)場(chǎng)景下配合適當(dāng)?shù)脑O(shè)計(jì),可以帶來(lái)意想不到的效果;

舉個(gè)常見(jiàn)的例子,現(xiàn)在幾乎很多公司都會(huì)用到nginx作為代理服務(wù)器,假如現(xiàn)在有這么個(gè)需求,需要做黑名單過(guò)濾,或者在網(wǎng)關(guān)這一層做流控,這該怎么做呢?

實(shí)現(xiàn)思路

  • 直接在nginx做配置黑名單,通過(guò)編寫(xiě)邏輯塊實(shí)現(xiàn);
  • 在服務(wù)端(Java)中編寫(xiě)過(guò)濾器,在過(guò)濾器中統(tǒng)一攔截;
  • 在服務(wù)端(Java)中編寫(xiě)攔截器,在攔截器中統(tǒng)一攔截;

這里列舉了3種實(shí)現(xiàn)的思路,至于實(shí)現(xiàn)方案,可能還有更多,但是我們想想,在nginx中編寫(xiě)邏輯塊貌似不是很多人擅長(zhǎng)的;在代碼層面做不是不可以,而是這樣一來(lái),在涉及到高并發(fā)的業(yè)務(wù)高峰期,這必然會(huì)對(duì)后端服務(wù)造成較大的壓力,那么還有沒(méi)有其他更好的處理辦法呢?

這就是要說(shuō)的lua,即nginx作為網(wǎng)關(guān)仍然作為代理服務(wù)器,由于nginx可以集成lua,于是使用lua進(jìn)行配合,來(lái)完成上面的業(yè)務(wù)實(shí)現(xiàn)的設(shè)計(jì);

ngx_lua模塊概念

  • ngx_lua模塊由淘寶技術(shù)團(tuán)隊(duì)開(kāi)發(fā),通過(guò)將lua解釋器集成進(jìn)Nginx;
  • 可采用lua腳本實(shí)現(xiàn)業(yè)務(wù)邏輯,由于lua的緊湊、快速以及內(nèi)建協(xié)程,所以在保證高并發(fā)服務(wù)能力的同時(shí)極大地降低了業(yè)務(wù)邏輯實(shí)現(xiàn)成本;
  • OpenRestry

  • OpenResty是一個(gè)基于Nginx與 Lua 的高性能 Web 平臺(tái),其內(nèi)部集成了大量精良的 Lua庫(kù)、第三方模塊以及大多數(shù)的依賴項(xiàng);用于方便地搭建能夠處理超高并發(fā)、擴(kuò)展性極高的動(dòng)態(tài) Web 應(yīng)用、Web 服務(wù)和動(dòng)態(tài)網(wǎng)關(guān);
  • OpenResty內(nèi)部已經(jīng)集成了Nginx和Lua,所以使用起來(lái)會(huì)更加方便;

簡(jiǎn)單來(lái)說(shuō),直接安裝并使用OpenRestry,就可以達(dá)到同時(shí)使用Nginx與Lua的效果,同時(shí)基于OpenRestry,還可以在內(nèi)部操作其他中間件,比如mysql,redis,kafka等,這樣就使得業(yè)務(wù)架構(gòu)在設(shè)計(jì)上具備了更大的靈活性;

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、進(jìn)入OpenResty目錄執(zhí)行配置

這一步有點(diǎn)類似于nginx的源碼安裝,進(jìn)行相關(guān)的環(huán)境變量的配置,這里直接使用默認(rèn)的就好;

./configure

4、 執(zhí)行命令:make && make install

5、進(jìn)入OpenResty的目錄配置nginx

進(jìn)入nginx目錄,可以看到里面的目錄和nginx自身安裝完畢后的配置幾乎一樣

進(jìn)入conf,找到nginx.conf配置文件,添加如下內(nèi)容:

location /lua { 
    default_type 'text/html'; 
    content_by_lua 'ngx.say(" <h1>hello,openRestry lua</h1>")'; 
}

6、啟動(dòng)nginx并測(cè)試

進(jìn)入nginx的sbin目錄下啟動(dòng)nginx

啟動(dòng)完成后,瀏覽器訪問(wèn)下服務(wù)器即可,可以看到nginx本身服務(wù)已啟動(dòng)

然后訪問(wèn)上面配置的lua地址,可以看到也能夠正常的訪問(wèn)到,說(shuō)明openrestry的模塊已經(jīng)安裝完畢

ngx_lua常用指令

使用Lua編寫(xiě)Nginx腳本的基本構(gòu)建塊是指令,指令用于指定何時(shí)運(yùn)行用戶Lua代碼以及如何使用結(jié)果,下面針對(duì)一些常用的指令做簡(jiǎn)單的說(shuō)明

1、init_by_lua*

該指令在每次Nginx重新加載配置時(shí)執(zhí)行,用來(lái)完成一些耗時(shí)操作模塊加載,或初始化一些全局配置

2、init_worker_by_lua*

該指令用于啟動(dòng)一些定時(shí)任務(wù),如心跳檢查、定時(shí)拉取服務(wù)器配置等

3、set_by_lua*

該指令只要用來(lái)給變量賦值,這個(gè)指令一次只能返回一個(gè)值,并將結(jié)果 值給Nginx中指定變量

4、rewrite_by_lua*

用于執(zhí)行內(nèi)部URL重寫(xiě)或者外部重定向,典型的如偽靜態(tài)化URL重 寫(xiě),本階段在rewrite處理階段的最后默認(rèn)執(zhí)行(和nginx自身的rewrite功能有類似的地方)

5、access_by_lua*

該指令用于訪問(wèn)控制,例如,只允許內(nèi)網(wǎng)IP訪問(wèn)

6、content_by_lua*

該指令是使用最多的指令,大部分任務(wù)是在這個(gè)階段完成的,其他過(guò)程往往為這個(gè)階段準(zhǔn)備數(shù)據(jù),正式處理往往都在本階段執(zhí)行

7、header_filter_by_lua*

用于設(shè)置應(yīng)答消息的頭部信息

8、body_filter_by_lua*

該指令對(duì)響應(yīng)數(shù)據(jù)進(jìn)行過(guò)濾,如截?cái)?、替換

9、log_by_lua*

該指令用于log請(qǐng)求處理階段,用Lua代碼處理日志,但并不替換原有 log處理

10、balancer_by_lua*

該指令主要作用是用來(lái)實(shí)現(xiàn)上游服務(wù)器的負(fù)載均衡器算法

11、ssl_certificate_by_*

該指令作用在Nginx和下游服務(wù)開(kāi)始一個(gè)SSL握手操作時(shí)將允許本配置項(xiàng)的Lua代碼

一個(gè)使用指令的需求

接下來(lái)針對(duì)上面提到的各種指令,來(lái)做一個(gè)簡(jiǎn)單的需求

nginx接收到請(qǐng)求后,根據(jù)參數(shù)中g(shù)ender傳入的值,如果gender傳入的是1 則在頁(yè)面上展示 “先生” , 如果gender傳入的是0,則在頁(yè)面上展示“女士”

代碼實(shí)現(xiàn)

注意:使用指令編寫(xiě)的基本步驟是,在nginx.conf模塊中,自定義localtion塊中編寫(xiě)lua的相關(guān)代碼即可

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;
 }

然后啟動(dòng)nginx做一下測(cè)試

1)訪問(wèn)服務(wù),不攜帶任何參數(shù)

這時(shí)候無(wú)任何返回信息

2)訪問(wèn)服務(wù),攜帶name參數(shù)

3)訪問(wèn)服務(wù),攜帶name和gender參數(shù)

更多的指令可以參照此類方式編寫(xiě),但是前提需要掌握一點(diǎn)lua的基本語(yǔ)法

lua操作redis

Redis在系統(tǒng)中經(jīng)常作為數(shù)據(jù)緩存、內(nèi)存數(shù)據(jù)庫(kù)使用,在各類互聯(lián)網(wǎng)項(xiàng)目中扮演著非常重要的作用;

Lua-resty-redis庫(kù)是OpenResty提供的一個(gè)操作Redis的接口庫(kù),可根據(jù)自己的業(yè)務(wù)情況做一些邏輯處理,適合做復(fù)雜的業(yè)務(wù)邏輯。所以下面將以Lua-resty-redis來(lái)進(jìn)行說(shuō)明。

lua-resty-redis環(huán)境準(zhǔn)備

1、提前安裝好redis并啟動(dòng)服務(wù)

2、測(cè)試下redis客戶端

lua-resty-redis提供了訪問(wèn)Redis的詳細(xì)API,包括創(chuàng)建對(duì)接、連 接、操作、數(shù)據(jù)處理等。這些API基本上與Redis的操作是對(duì)應(yīng)起來(lái)的

lua-resty-redis常用API

1、lua中導(dǎo)入redis依賴

redis = require "resty.redis"

2、new,創(chuàng)建一個(gè)Redis對(duì)象

redis,err = redis:new()

3、創(chuàng)建redis連接

  • ok:連接成功返回 1,連接失敗返回nil;
  • err:返回對(duì)應(yīng)的錯(cuò)誤信息;

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

4、設(shè)置請(qǐng)求操作Redis的超時(shí)時(shí)間

redis:set_timeout(time)

5、close,關(guān)閉連接

  • 關(guān)閉當(dāng)前連接,成功返回1;
  • 失敗返回nil和錯(cuò)誤信息;

ok,err = redis:close()

補(bǔ)充說(shuō)明:

在lua-resty-redis中,所有的Redis命令都有自己的方法;方法名字和命令名字相同,只是全部為小寫(xiě);

具體實(shí)現(xiàn)效果展示

在nginx.conf模塊下,添加如下的location內(nèi)容

location /redis {
    default_type "text/html";
    content_by_lua_block {
        local redis = require "resty.redis"     -- 引入 Redis
        local redisObj = redis:new()            --創(chuàng)建Redis對(duì)象
        redisObj:set_timeout(3000)              --設(shè)置超時(shí)數(shù)據(jù)為3s
        local ok,err = redisObj:connect("IP",6379)    --設(shè)置redis連接信息
        if not ok then                          --判斷是否連接成功
            ngx.say("failed to connection redis",err)
            return
        end
        ok,err = redisObj:set("username","TOM")     --存入 數(shù)據(jù)
        if not ok then  --判斷是否存入成功
            ngx.say("failed to set username",err)
            return
        end
        local res,err = redisObj:get("username")    --從 redis中獲取數(shù)據(jù)
        ngx.say(res) --將數(shù)據(jù)寫(xiě)會(huì)消息體中
        redisObj:close()
    }
}

重啟nginx,進(jìn)行測(cè)試,直接在瀏覽器訪問(wèn)一下如下地址,可以看到數(shù)據(jù)成功寫(xiě)入到redis


ngx_lua操作Mysql

MySQL是一個(gè)使用廣泛的關(guān)系型數(shù)據(jù)庫(kù)。在ngx_lua中,MySQL有兩種訪問(wèn)模式,分別是

  • 用ngx_lua模塊和lua-resty-mysql模塊: 這兩個(gè)模塊是安裝OpenResty時(shí)默認(rèn)安裝的;
  • 使用drizzle_nginx_module(HttpDrizzleModule)模塊:需要單獨(dú)

安裝,這個(gè)庫(kù)現(xiàn)不在OpenResty中

lua-resty-mysql

lua-resty-mysql是OpenResty開(kāi)發(fā)的模塊,使用靈活、功能強(qiáng)大,適合復(fù)雜的業(yè)務(wù)場(chǎng)景,同時(shí)支持存儲(chǔ)過(guò)程訪問(wèn);

lua-resty-mysql實(shí)現(xiàn)數(shù)據(jù)庫(kù)查詢

1、準(zhǔn)備好mysql服務(wù)

2、提前創(chuàng)建一張表

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;

并提前準(zhǔn)備幾條數(shù)據(jù)

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說(shuō)明

1、引入"resty.mysql"模塊

local mysql = require "resty.mysql"

2、創(chuàng)建MySQL連接對(duì)象

遇到錯(cuò)誤時(shí),db為nil,err為錯(cuò)誤描 述信息

db,err = mysql:new()

3、創(chuàng)建連接對(duì)象

ok,err=db:connect(options)

options是一個(gè)參數(shù)的 Lua表結(jié)構(gòu),里面包含數(shù)據(jù)庫(kù)連接的相關(guān)信息

  • host:服務(wù)器主機(jī)名或IP地址
  • port:服務(wù)器監(jiān)聽(tīng)端口,默認(rèn)為3306
  • user:登錄的用戶名
  • password:登錄密碼
  • database:使用的數(shù)據(jù)庫(kù)名

4、設(shè)置子請(qǐng)求的超時(shí)時(shí)間(ms)

包括connect方法

db:set_timeout(time)

5、關(guān)閉當(dāng)前MySQL連接并返回狀態(tài)

如果成功,則返回1;如果出現(xiàn)任 何錯(cuò)誤,則將返回nil和錯(cuò)誤描述

db:close()

6、異步向遠(yuǎn)程MySQL發(fā)送一個(gè)查詢

如果成功則返回成功發(fā)送的字節(jié) 數(shù);如果錯(cuò)誤,則返回nil和錯(cuò)誤描述

bytes,err=db:send_query(sql)

7、從MySQL服務(wù)器返回結(jié)果中讀取一行數(shù)據(jù)

  • res返回一個(gè)描述OK包 或結(jié)果集包的Lua表
  • rows指定返回結(jié)果集的最大值,默認(rèn)為4
  • 如果是查詢,則返回一個(gè)容納多行的數(shù)組。每行是一個(gè)數(shù)據(jù)列的 key-value對(duì)
res, err, errcode, sqlstate = db:read_result() res, err, errcode, sqlstate = db:read_result(rows)

返回結(jié)果類似下面這樣

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

如果是增刪改,則返回類似如下數(shù)據(jù)

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

返回值說(shuō)明:

  • res:操作的結(jié)果集
  • err:錯(cuò)誤信息
  • errcode:MySQL的錯(cuò)誤碼,比如1064
  • sqlstate:返回由5個(gè)字符組成的標(biāo)準(zhǔn)SQL錯(cuò)誤碼,比如 42000

具體操作案例

將下面的內(nèi)容添加到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()
    } 
}

可以看到,通過(guò)訪問(wèn)mysql這個(gè)路徑,成功查詢到數(shù)據(jù)庫(kù)中ID為1的這條數(shù)據(jù)

使用cjson對(duì)查詢結(jié)果進(jìn)行格式化

從上面的返回結(jié)果來(lái)看,這種形式的返回?cái)?shù)據(jù)在解析的時(shí)候其實(shí)并不是很友好,于是可以使用lua-cjson處理查詢結(jié)果

使用步驟

步驟一:引入cjson

local cjson = require “cjson”

步驟二:調(diào)用cjson的encode方法進(jìn)行類型轉(zhuǎn)換

cjson.encode(res)

下面對(duì)上面程序模塊做簡(jiǎn)單的改造

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

然后再次進(jìn)行測(cè)試,這時(shí)候就以json的格式對(duì)數(shù)據(jù)進(jìn)行了展現(xiàn)

增刪改操作

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") 
			-- 插入數(shù)據(jù)
			--local res,err,errcode,sqlstate = db:query("insert into users(id,username,birthday,salary) values(3,'lifei','1995-10-17',3000)")
			-- 修改數(shù)據(jù)
			--local res,err,errcode,sqlstate = db:query("update users set username='lisi' where id = 1")
			-- 刪除數(shù)據(jù)
			--local res,err,errcode,sqlstate = db:query("delete from users where id = 2")
            db:close()
    } 
}

到此這篇關(guān)于nginx集成lua操作mysql的過(guò)程解析的文章就介紹到這了,更多相關(guān)nginxlua操作mysql內(nèi)容請(qǐng)搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!

美國(guó)快速服務(wù)器

版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。

相關(guān)文章

實(shí)時(shí)開(kāi)通

自選配置、實(shí)時(shí)開(kāi)通

免備案

全球線路精選!

全天候客戶服務(wù)

7x24全年不間斷在線

專屬顧問(wèn)服務(wù)

1對(duì)1客戶咨詢顧問(wèn)

在線
客服

在線客服:7*24小時(shí)在線

客服
熱線

400-630-3752
7*24小時(shí)客服服務(wù)熱線

關(guān)注
微信

關(guān)注官方微信
頂部