当前位置:首页 > 天道酬勤 > 正文内容

openresty udp(nginx怎么用)

张世龙2021年12月21日 19:17天道酬勤1260

Nginx Lua操作Redis

本节介绍如何使用开源lua-resty-Redis模块在Lua脚本中连接和访问redis。 本模块的官方网站如下

359 Github.com /开放城市/Lua-resty-redis。 准备实战案例分析:本节中使用的配置文件是源项目的nginxredis-demo.conf文件。 在运行本节中的实例之前,请将启动脚本openresty-start.bat或openresty-start.sh中的PROJECT_CONF变量的值设置为nginx-redis-demo.conf

在使用

Redis的CRUD基本操作

Lua模块lua-resty-redis之前,请在官网上下载resty/redis.lua库文件,并将其添加到包含项目项目的Lua外部库路径中lua-resty-Redis正式表明,大多数redis操作命令都实现了同名的Lua API方法。

以下是使用Lua模块lua-resty-Redis操作redis的简单示例

示例,代码如下:

local redis=需要' resty.redis '

本地配置=请求(luascript.module.config.redis-config );

---开始调试

localmobdebug=require (luascript.initial.mob调试);

mob调试. start (;

- -设置超时时间

本地红色=redis :新建(

- -以毫秒为单位设置超时时间

red :组_时间输出(配置.时间输出,配置.时间输出,配置.时间输出) ) )。

- -连接到服务器

local ok,err=red :连接(配置.主机名称,配置.端口) )。

if not ok then

ngx.say ('故障诊断连接: ',错误) ) ) ) ) ) ) ) )。

返回

结束

- -设定值

ok,err=红色:组(' Dog ','安妮动画' ) ) ) ) )。

if not ok then

NGX.Say('failedtosetdog: ',err,' br ' ) )

返回

else

NGX.Say('setdog:ok ',' br ' ) )

结束

- -取值

local res,err=red:get('dog ) ) ) )。

- -进行空中示威

if not RES或RES==NGX .空then

ngx.say ('故障诊断程序: ',错误,' br ' ) )

返回

else

NGX.Say('getdog:ok ',' br ',res,' br ' ) )

结束

- -通过批量操作,减少网络I/o次数

red :初始化管线(

red :组(' cat ',' cat 1' ) ) ) ) ) ) ) ) ) ) ) ) )。

red :组(' horse 1 '、' horse 1) ) ) )。

red :获取(cat );red :获取(horse ) ) )。

red :获取(文档) )。

本地结果,错误=红色:提交_管线(

if not结果三角网

ngx.say (' failedtocommitthepipelinedrequests : ',err ) ) ) ) ) ) )。

返回

结束

for i,发行版,结果,do

if类型(RES )=='表' then

if RES [1]==假三角网

ngx.say ('失败命令',I,' : ',res[2],' br ' ) )

else

- -处理表容器

ngx.say (成功指令,I,) : ),res[i],br ) )

结束

else

- -处理变量

NGX.Say (安全命令),I, ),res,br ) )

结束

结束

- -轻松关闭连接

local ok,err=red :关闭(

if not ok then

ngx.say (故障诊断程序:错误) ) ) ) )。

返回

else

ngx.say (安全措施) )。

end以上的Lua脚本在工程目录的luaScript/Redis/RedisDemo.lua文件中,完成了以下redis操作。

(1)与Redis服务器连接。

)2)根据key设定缓存值。

)3)从key获取缓存值。

4 )批量Redis操作。

)5)简单地关闭Redis连接。

位于nginx-redis-demo上。

conf配置文件中编写一个location配置块来使用该脚本,具体代码如下:

简单操作演示 #redis CRUD简单操作演示 location /redis_demo { content_by_lua_file luaScript/redis/RedisDemo.lua; }

修改nginx-redis-demo.conf文件后需要重启OpenRestry,然后可以使用浏览器访问其地址/redis_demo,具体的访问结果如图8-21所示。

图8-21 Redis CRUD简单操作演示的访问结

RedisDemo.lua通过require导入了redis-config.lua配置文件,该文件定义了整个项目都需要使用的全局Redis配置信息,其代码如下:

--定义一个统一的redis配置模块 --统一的模块对象 local _Module = { --redis服务器的地址 host_name = "192.168.233.128"; --redis服务器的端口 port = "6379"; 服务器的数据库 --redis服务器的数据库 db = "0"; --redis服务器的密码 password = '123456'; --连接超时时长 timeout = 20000; --线程池的连接数量 pool_size = 100; --最大的空闲时间,单位:毫秒 pool_max_idle_time = 10000; } return _Module

实战:封装一个操作Redis的基础类

通过Lua操作Redis会涉及获取连接、操作数据、连接回收等基础性工作,这里建议将这些基础性工作封装到一个Redis操作的基础类,主要的代码如下:

local redis = require "resty.redis" local basic = require("luaScript.module.common.basic"); local config = require("luaScript.module.config.redis-config"); --连接池大小 local pool_size = config.pool_size; --最大的空闲时间,单位:毫秒 local pool_max_idle_time = config.pool_max_idle_time; --一个统一的模块对象 local _Module = {} _Module.__index = _Module --类的方法new function _Module.new(self) local object = { red = nil } setmetatable(object, self) return object end --获取redis连接 function _Module.open(self) local red = redis:new() --设置超时的时间为 2 sec,connect_timeout, send_timeout, read_timeout red:set_timeout(config.timeout, config.timeout, config.timeout); local ok, err = red:connect( config.host_name, config.port) if not ok then basic.error("连接redis服务器失败: ", err) return false; end if config.password then red:auth(config.password) end if config.db then red:select(config.db) end basic.log("连接redis服务器成功") self.red = red; return true; end --缓存值 function _Module.setValue(self, key, value) ok, err = self.red:set(key, value) if not ok then basic.error("redis缓存设置失败") return false; end basic.log("set result ok") return true; end --值递增 function _Module.incrValue(self, key) ok, err = self.red:incr(key) if not ok then basic.error("redis缓存递增失败 ") return false; end basic.log("incr ok") return true; end --过期 function _Module.expire(self, key, seconds) ok, err = self.red:expire(key, seconds) if not ok then basic.error("redis设置过期失败 ") return false; end return true; end --获取值 function _Module.getValue(self, key) local resp, err = self.red:get(key) if not resp then basic.error("redis缓存读取失败 ") return nil; end return resp; end --省略封装的其他Redis操作方法 --将连接还给连接池 function _Module.close(self) if not self.red then return end local ok, err = self.red:set_keepalive(pool_max_idle_time, pool_size) if not ok then basic.error("redis set_keepalive执行失败 ") end basic.log("redis连接释放成功") end return _Module

此基础操作类的名称为RedisOperator,需要使用时通过require("luaScript.redis.RedisOperator")导入即可。

在Lua中使用Redis连接池

在示例代码RedisDemo.lua脚本中,每一次客户端请求,luaresty-redis模块都会创建一个新的Redis连接。在生产环境中,每一次请求都开启一个服务器新连接会导致以下问题:

(1)连接资源被快速消耗。

(2)网络一旦抖动,会有大量TIME_WAIT连接产生,需要定期重启服务程序或机器。

(3)服务器工作不稳定,QPS忽高忽低。

(4)性能普遍上不去。

为什么会出现这些性能问题呢?因为每一次传输数据,我们需要完成创建连接、收发数据、拆除连接3个基本步骤,在低并发场景下每次请求完整走完这3步基本上不会有什么问题。然而,一旦挪到高并发应用场景,性能问题就出现了。

性能优化的第一件事情就是把短连接改成长连接,可以减少大量创建连接、拆除连接的时间。从性能上来说肯定要比短连接好很多,但还是有比较大的浪费。

性能优化的第二件事情就是使用连接池。通过一个连接池pool将所有长连接缓存和管理起来,谁需要使用,就从这里取走,干完活立马放回来。

实际上,大家在开发过程中用到的连接池是非常多的,比如HTTP连接池、数据库连接池、消息推送连接池等。实际上,几乎所有点到点之间的连接资源复用都需要通过连接池完成。在OpenResty中,lua-resty-redis模块管理了一个连接池,并且定义了set_keepalive方法完成连接的回收和复用。set_keepalive方法的语法如下:

ok, err = red:set_keepalive(max_idle_timeout, pool_size)

该方法将当前的Redis连接立即放入连接池。其中,max_idle_timeout参数指定连接在池中的最大空闲超时时长(以毫秒为单位);pool_size参数指定每个Nginx工作进程的连接池的最大连接数。如果入池成功,就返回1;如果入池出现错误,就返回nil,并返回错误描述字符串。

下面看一个连接回收的示例,具体的代码如下:

location /pool_demo { content_by_lua_block { local redis = require "resty.redis" local config = require("luaScript.module.config.redis-config"); --连接池大小 local pool_size = config.pool_size; --最大的空闲时间,单位:毫秒 local pool_max_idle_time = config.pool_max_idle_time; local red = redis:new() local ok, err = red:connect(config.host_name, config.port) if not ok then ngx.say("failed to connect: ", err) return else ngx.say("succeed to connect redis", "<br>") end red: auth(config.password) --red: set_keepalive(pool_max_idle_time, pool_size) --① 坑 ok, err = red:set("dog", "an animal") if not ok then --red: set_keepalive(pool_max_idle_time, pool_size) --② 坑 return end --③ 正确回收 red: set_keepalive(pool_max_idle_time, pool_size) ngx.say("succeed to collect redis connection", "<br>") } }

以上代码中,有3个需要注意的地方,具体介绍如下:

①坑:只有数据传输完毕、Redis连接使用完成之后,才能调用set_keepalive方法将连接放到mldzh里,set_keepalive方法会立即将red连接对象转换到closed状态,后面的Redis调用将出错。

②坑:如果设置错误,那么red连接对象不一定可用,不能把可用性存疑的连接放回mldzh里,如果另一个请求从连接池获取到一个不能用的连接,就会直接报错。

③正确回收:此处的set_keepalive方法调用是正确的。

以上代码处于nginx-redis-demo.conf文件中,修改后需要重启OpenRestry,然后可以使用浏览器访问其地址/pool_demo,具体的访问结果如图8-22所示。

图8-22 Redis连接池演示实例的执行结果

set_keepalive方法完成连接回收之后,下一次通过red:

connect(...)获取连接时,connect方法在创建新连接前会在连接池中查找空闲连接,只有查找失败才会真正创建新连接。

总之,作为一个专业的服务端开发工程师,大家必须要对连接池有较深理解,其实不论是Redis连接池、HTTP连接池,还是数据库连接池,甚至是线程池,其原理都是差不多的。

本文给大家讲解的内容是Nginx/OpenResty详解,Nginx Lua编程,Nginx Lua操作Redis

下篇文章给大家讲解的是 Nginx/OpenResty详解,Nginx Lua编程, Nginx Lua编程实战案例;觉得文章不错的朋友可以转发此文关注小编;感谢大家的支持!

扫描二维码推送至手机访问。

版权声明:本文由花开半夏のブログ发布,如需转载请注明出处。

本文链接:https://www.zhangshilong.cn/work/26526.html

分享给朋友:

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。