Nginx高级应用:lua + OpenResty

发布时间:2026/11/6 8:25:43
Nginx高级应用:lua + OpenResty Nginx高级应用应用场景该技术不仅仅是应用于, 广告缓存只是常用于做广告的缓存广告缓存载入与读取对于一个应用来多每天都会有很多的用户来访问, 那么访问最多的就是首页了而对于首页这种高访问且页面数据并不是经常的变化为了减轻服务器的压力直接将其制作成一个静态的页面进行展示基本流程Nginx都学习过了可以通过反向代理实现网关负载均衡的 服务器用户发送请求首先通过 nginx , 通过nginx代理负载均衡请求对应的网关…模块。本次就是在用户登录/常用的操作, 请求时经过 nginx请求在nginx中完成 调用redis数据操作直接返回结果但niginx并不具备编程语言的特性if else逻辑判断访问数据库 redis; 它只是一个负载均衡器;所以需要通过lua 嵌入式语言来完成首先访问nginx 我们可以采用缓存的方式先从nginx本地缓存中获取获取到直接响应如果没有获取到再次访问redis我们可以从redis中获取数据如果有 则返回并缓存到nginx中如果没有获取到,再次访问mysql我们从mysql中获取数据再将数据存储到redis中。而这里面我们都可以使用LUA脚本嵌入到程序中执行这些查询相关的业务。Lua简介Lua 是一种轻量小巧的脚本语言用标准C语言编写并以源代码形式开放c 作为底层语言写的东西都快其设计目的是为了嵌入应用程序中从而为应用程序提供灵活的扩展和定制功能。特性轻量级:使用 C语言编写并以源代码形式开放编译后仅仅一百余K可以很方便的嵌入别的程序里。可扩展:** Lua提供了非常易于使用的扩展接口和机制**内置了大量开发好的脚本文件 mysql redis....(通常是C或C)提供这些功能Lua可以使用它们就像是本来就内置的功能一样。其它特性:支持面向过程(procedure-oriented)编程和函数式编程(functional programming)自动内存管理只提供了一种通用类型的表table实现数组哈希表集合对象通过闭包和table可以很方便地支持面向对象编程所需要的一些关键机制比如数据抽象虚函数继承和重载等应用场景游戏开发独立应用脚本Web 应用脚本扩展和数据库插件如MySQL Proxy 和 MySQL WorkBench安装并不需要安装windows 只需要配置一下系统的环境变量即可:环境变量也只是为了可以在系统的任意对方可以使用Path:D:\WSMwork\lua(本人的安装路径**lua53 或 lua53 -i **都可以启动lua入门Lua创建hello.lua文件打印print(输出内容);创建文件输入print(hello);直接 cmd 运行执行命令lua53 文件名.luaLUA的基本语法(了解)介绍lua有交互式编程和脚本式编程:交互式编程就是 启动lua直接输入语法就能直接执行。脚本式编程需要编写脚本然后再执行命令 执行脚本才可以。一般采用脚本式编程。例如编写一个hello.lua的文件输入文件内容并执行lua53 hell.lua即可lua53 不同版本的lua 执行要指定版本号语法都是一样的只是操作方式不同…下面了解lua 基本语法脚本式编程创建 .lua文件, 进行执行...注释hello.lua-- 单行注释--[[ 多行注释 多行注释 ]]--定义变量同Java 一样有全局变量和局部变量全局整个文件可以使用局部指定方法内可以使用hello.lua-- 全局变量赋值a1-- 局部变量赋值localb2-- ..拼接print(a..b)print(a..:..b)a张三字符可以使用单引号 或 双引号来表示utf-8可能会乱码建议文件编码 ANSl如果变量没有初始化则 它的值为nil 这和java中的null不同。案例数值运算还是通过 - * /Lua中的数据类型Lua 是动态类型语言变量不要类型定义,只需要为变量赋值。值可以存储在变量中作为参数传递或结果返回。Lua 中有 8 个基本类型分别为nil、boolean、number、string、userdata、function、thread 和 table。type( 值 ) 返回值的类型print(type(Hello world))-- stringprint(type(10.4*3))-- number 包含double intprint(type(print))-- functionprint(type(type))-- functionprint(type(true))-- booleanprint(type(nil))-- nil流程控制if语句类似于Orcal的存储过程if 语句 由一个布尔表达式作为条件判断其后紧跟其他语句组成。-- 条件括号,可选加或不加if(布尔表达式)then--[ 在布尔表达式为 true 时执行的语句 --]endif…elseif…eles…end语句if 语句可以与 elseif 语句, else搭配使用, 在 if 条件表达式为 false 时执行 else 语句代码块。if——elseif(布尔表达式)then--[ 布尔表达式为 true 时执行该语句块 --]else--[ 布尔表达式为 false 时执行该语句块 --]endif——esleif——elseif——else——endlocalage15if(age18)thenprint(成年人)elseifage18thenprint(未成年)elseprint(未出生)end测试循环while循环[满足条件就循环] do … endwhile 循环语句在判断条件为 true 时会重复执行循环体语句。while(条件true执行)doprint(‘执行循环内容…’)endfor循环for 循环语句可以重复执行指定语句重复次数可在 for 语句中控制。forvarexp1,exp2,exp3doprint(‘执行循环内容…’)end--[[ var 从 exp1 变化到 exp2 每次变化以 exp3 为步长递增 var 并执行一次 “执行体”。 exp3 是可选的如果不指定默认为1。 ]]--repeat…until语句[满足条件结束]repeat…until 循环语句不同于 for 和 while循环for 和 while 循环的条件语句在当前循环执行开始时判断repeat 无论如何都会执行一次until 条件成立true则结束循环repeatprint(‘执行循环内容…’)until(true退出循环)函数lua中也可以定义函数类似于java中的方法。--[[ 函数返回两个值的最大值 --]]functionmax(num1,num2)if(num1num2)thenresultnum1;elseresultnum2;endreturnresult;end-- 调用函数print(两值比较最大值为 ,max(10,4))print(两值比较最大值为 ,max(5,6))执行之后的结果表tabletable 是 Lua 的一种数据结构用来帮助我们创建不同的数据类型如数组、字典、对象等。-- 初始化表mytable {}-- 指定值mytable[1] Lua-- 移除引用mytable nil测试Demotable{}table[0]张三1table[1]张三2table[2]张三3--table 是一个对象print(table)--通过下标来获取值print(table[0])--table nil 来清空表/对象tablenuiprint(table)print(table[0])模块模块定义模块类似于一个封装库Lua 5.1 开始Lua 加入了标准的模块管理机制可以把一些公用的代码放在一个文件里;以 API 接口的形式在其他地方调用有利于代码的重用和降低代码耦合度。创建一个文件叫module.lua别忘了中文乱码文件格式设置ASCII码module.lua-- 文件名为 module.lua-- 定义一个名为 module 的模块,和文件名一样module{}-- 定义一个常量module.constant这是一个常量-- 定义一个函数 module.func1functionmodule.func1()print(这是一个公有函数)end-- 定义一个局部(私有) 方法-- 因此是不能从外部访问模块里的这个私有函数必须通过模块里的公有函数来调用localfunctionfunc2()print(这是一个私有函数)end-- 模拟调用私有方法...functionmodule.func3()func2()endreturnmodule模块的结构就是一个 table 的结构因此可以像操作调用 table 里的元素那样来操作调用模块里的常量或函数。require 函数require用于引入其他的模块类似于java中的类要引用别的类的效果。要引入的模块要放在一个文件夹下可以是子文件不然找不到require(模块名)-- 或require模块名OpenResty简介OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。简单来说 OpenResty 就是 Niginx,集成了Lua的Niginx 使其具备了编程特性由 OpenResty 团队自主开发OpenResty下载系统配置目录结构D:\WSMwork\openresty-1.15.8.2-win64\lualib\resty 路径下包含了很多的lua模块配置配置lua库位置修改openresty-1.15.8.2-win64\conf\nginx.conf文件接下来的大部分操作都是在: 自定义的lua.conf文件中执行lua.conf自定义的lua.conf#给nginx 分内存 128m 兆 缓存大小用于存放热点数据频繁使用的数据lua_shared_dict my_cache 128m;#nginx服务server{listen9090;#指定端口9090默认80server_name _;#静态模板地址设置...set$template_location/templates;set$template_rootD:/templates;#填写对应的地址...#nginx分流的请求路径...location /mylua{default_type text/html;#通过 content_by_lua_block{ lua的执行代码 } ngx.say(是lua的浏览器输出方法)content_by_lua_block{localage20ifage18thenngx.say(18);elsengx.say(18);end}}}这就是一个正常的 nginx的配置代码content_by_lua_block{ }lua的执行操作就写在这里是nginx拥有了编程语言的特性OpenResty1.9.3.2以前是content_by_lua{ }可通过nginx -v查看版本号ngx.say(‘是lua的浏览器输出方法’)就像Java的 Out打印流一样启动/刷新 nginx启动命令OpenResty目录下cmdnginx.exe没有异常就是执行成功重启刷新命令当修改了文件频繁调用 nginx.exe是启动开启进行造成堵塞正确的方法是刷新重启OpenResty目录下cmdnginx.exe -s reload测试nginx端口占用启动报错bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a …)nginx.conf文件下还有默认的 80端口启动.. 可能会与电脑里某个端口冲突, 直接更改即可或者停止进程Windows操作netstat -aon | findstr :8080表示端口tasklist|findstr 进程号OpenResty引入lua 文件在nginx 配置中写lua 代码不方便书写可以直接在外面写好调用即可location /mylua2{default_type text/html;content_by_lua_file D:/WSMwork/myweb.lua;}#content_by_lua_file 引入外部的lua文件, 分号结尾;content_by_lua_file引入外部的.lua 文件定义一个文件 myweb.lua外部文件~刷新nginxopenresty中发起http请求有些场景是需要nginx在进行请求转发这样就需要nginx需要有发起http请求的能力nginx服务发起http请求区分内部请求 和 外部请求为了方便测试启动一个微服来查看lua 脚本myweb.lua--设置编码格式ngx.header.content_typetext/html;charsetutf8--调用ngx 模块中的方法返回请求urllocaluri_argsngx.req.get_uri_args()--获取请求参数!localzzuri_args[zz]--获取http 模块require( );localhttprequire(resty.http)--http模块 new( ) 一个httpc对象localhttpchttp.new()--..拼接参数 wdlocalresphttpc:request_uri(http://127.0.0.1:9002/info/hello/..zz,{methodGET,--get请求keepalivefalse--无论如何都请求;})--返回参结果打印结果localvalresp.body ngx.say(val)测试注意这里的参数是在 nginx9090端口的请求参数require(“resty.http”)就是这个lua模块负载发送请求OpenResty 中存在着很多的lua脚本模块…获取POST请求参数跟get 非常类似…ngx.req.read_body()--获取请求urllocalargngx.req.get_post_args()--参数集合 Map类型--声明几个用于存储的空对象idnildeptnamenil--循环参数集合fork,vinpairs(arg)do--判断参数,key 进行参数赋值ifkidthenidvendifkdeptnamethendeptnamevendend--页面输出ngx.say(deptname: ,deptname)ngx.say(id: ,id)使用postman 进行Post请求openresty中使用redis模块在一些高并发的场景中我们常常会用到缓存技术现在我们常用的分布式缓存redis是最知名的我们需要引入redis模块 require “resty.redis”lua 脚本myweb.lua-- 定义私有方法localfunctionclose_redis(red)ifnotredthenreturnend-- 释放连接(连接池实现)毫秒localpool_max_idle_time10000-- 连接池大小localpool_size100localok,errred:set_keepalive(pool_max_idle_time,pool_size)locallogngx_logifnotokthenlog(ngx_ERR,set redis keepalive error : ,err)endend-- 连接redislocalredisrequire(resty.redis)--引入模块localredredis.new()red:set_timeout(1000)localip127.0.0.1localport6379-- local pwd ok 本人没有密码直接注释-- 连接测试 ip 端口是否正确...ok,errred:connect(ip,port)ifnotokthenngx.say(failed to auth: ,err)returnclose_redis(red)end-- 密码是否正确 没有密码直接注释--[[ ok, err red:auth(pwd) if not ok then ngx.say(failed to auth: , err) return close_redis(red) end ]]----获取redis第一个库,redis一共16给库red:select(0)red:set(msg,test ngx hello)--set存入一个msg key,值:test ngx hello-- get根据key查找... 并处理异常localresp,errred:get(msg)ifnotrespthenngx.say(get msg error : ,err)returnclose_redis(red)end--打印关闭资源ngx.say(msg : ,resp)close_redis(red)记得要启动redis 哦安装目录下redis-server.exe查看所以key测试直接网关请求openresty中操作mysql数据库既然要数据库操作那么就搞个数据库吧mysqllua 脚本myweb.lua--创建连接mysql模块localmysqlrequireresty.mysql-- connect to mysql;localdb,errmysql:new()ifnotdbthenreturnfalse--没连上关闭end--超时时间db:set_timeout(1000)--设置连接信息localok,err,errno,sqlstatedb:connect{host127.0.0.1,--ipport3306,--端口databasebook,--连接的数据库userroot,--用户passwordok,--密码max_packet_size1024*1024--字节大小 1m}--验证是否连接上ifnotokthenngx.say(connect mysql failed)returnfalse--没连上关闭endifdbfalsethenngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)returnendngx.say(----------查询数据----------------,br/)res,err,errcode,sqlstatedb:query(SELECT * FROM bookinfo)--实际情况,可能还需要拼接参数....--没有数据,返回...异常!ifnotresthenngx.say(bad result: ,err,: ,errcode,: ,sqlstate,.)returnend--获取JSON 模块localcjsonrequirecjson--JSON翻译,页面输出ngx.say(result: ,cjson.encode(res))--如果是新增...--[[ --如果没有返回结果,新增异常提示 if not res then ngx.say(insert failed) return end --返回影响行数 ngx.say(insert rows :, res.affected_rows,, id, res.insert_id, br/) ]]--结果测试扩展推荐使用 nginx 引用外部的lua使用方便排错如果出现错误直接控制台运行lua 脚本即可结构清晰…

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询