热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

openrestyudp(nginx怎么用)

NginxLua操作Redis本节介绍如何使用开源的lua-resty-redis模块在Lua脚本中连接和访问Redis,该模块的官方网址为https:github.comop


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", "
")
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", "
")
}
}

以上代码中,有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编程实战案例;觉得文章不错的朋友可以转发此文关注小编;感谢大家的支持!

推荐阅读
  • ### 优化后的摘要本学习指南旨在帮助读者全面掌握 Bootstrap 前端框架的核心知识点与实战技巧。内容涵盖基础入门、核心功能和高级应用。第一章通过一个简单的“Hello World”示例,介绍 Bootstrap 的基本用法和快速上手方法。第二章深入探讨 Bootstrap 与 JSP 集成的细节,揭示两者结合的优势和应用场景。第三章则进一步讲解 Bootstrap 的高级特性,如响应式设计和组件定制,为开发者提供全方位的技术支持。 ... [详细]
  • 浏览器作为我们日常不可或缺的软件工具,其背后的运作机制却鲜为人知。本文将深入探讨浏览器内核及其版本的演变历程,帮助读者更好地理解这一关键技术组件,揭示其内部运作的奥秘。 ... [详细]
  • 本文总结了一些开发中常见的问题及其解决方案,包括特性过滤器的使用、NuGet程序集版本冲突、线程存储、溢出检查、ThreadPool的最大线程数设置、Redis使用中的问题以及Task.Result和Task.GetAwaiter().GetResult()的区别。 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • 在JavaWeb开发中,文件上传是一个常见的需求。无论是通过表单还是其他方式上传文件,都必须使用POST请求。前端部分通常采用HTML表单来实现文件选择和提交功能。后端则利用Apache Commons FileUpload库来处理上传的文件,该库提供了强大的文件解析和存储能力,能够高效地处理各种文件类型。此外,为了提高系统的安全性和稳定性,还需要对上传文件的大小、格式等进行严格的校验和限制。 ... [详细]
  • 阿里巴巴终面技术挑战:如何利用 UDP 实现 TCP 功能?
    在阿里巴巴的技术面试中,技术总监曾提出一道关于如何利用 UDP 实现 TCP 功能的问题。当时回答得不够理想,因此事后进行了详细总结。通过与总监的进一步交流,了解到这是一道常见的阿里面试题。面试官的主要目的是考察应聘者对 UDP 和 TCP 在原理上的差异的理解,以及如何通过 UDP 实现类似 TCP 的可靠传输机制。 ... [详细]
  • 本文深入探讨了NoSQL数据库的四大主要类型:键值对存储、文档存储、列式存储和图数据库。NoSQL(Not Only SQL)是指一系列非关系型数据库系统,它们不依赖于固定模式的数据存储方式,能够灵活处理大规模、高并发的数据需求。键值对存储适用于简单的数据结构;文档存储支持复杂的数据对象;列式存储优化了大数据量的读写性能;而图数据库则擅长处理复杂的关系网络。每种类型的NoSQL数据库都有其独特的优势和应用场景,本文将详细分析它们的特点及应用实例。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 提升 Kubernetes 集群管理效率的七大专业工具
    Kubernetes 在云原生环境中的应用日益广泛,然而集群管理的复杂性也随之增加。为了提高管理效率,本文推荐了七款专业工具,这些工具不仅能够简化日常操作,还能提升系统的稳定性和安全性。从自动化部署到监控和故障排查,这些工具覆盖了集群管理的各个方面,帮助管理员更好地应对挑战。 ... [详细]
  • 本文详细介绍了如何使用OpenSSL自建CA证书的步骤,包括准备工作、生成CA证书、生成服务器待签证书以及证书签名等过程。 ... [详细]
  • 您的数据库配置是否安全?DBSAT工具助您一臂之力!
    本文探讨了Oracle提供的免费工具DBSAT,该工具能够有效协助用户检测和优化数据库配置的安全性。通过全面的分析和报告,DBSAT帮助用户识别潜在的安全漏洞,并提供针对性的改进建议,确保数据库系统的稳定性和安全性。 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • 在ElasticStack日志监控系统中,Logstash编码插件自5.0版本起进行了重大改进。插件被独立拆分为gem包,每个插件可以单独进行更新和维护,无需依赖Logstash的整体升级。这不仅提高了系统的灵活性和可维护性,还简化了插件的管理和部署过程。本文将详细介绍这些编码插件的功能、配置方法,并通过实际生产环境中的应用案例,展示其在日志处理和监控中的高效性和可靠性。 ... [详细]
  • 在List和Set集合中存储Object类型的数据元素 ... [详细]
  • 在 Axublog 1.1.0 版本的 `c_login.php` 文件中发现了一个严重的 SQL 注入漏洞。该漏洞允许攻击者通过操纵登录请求中的参数,注入恶意 SQL 代码,从而可能获取敏感信息或对数据库进行未授权操作。建议用户尽快更新到最新版本并采取相应的安全措施以防止潜在的风险。 ... [详细]
author-avatar
金爽20111018
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有