OpenResty使用Lua笔记
创始人
2024-12-26 04:07:03
0

文章目录

  • 一、基础
    • 1、常用
    • 2、使用局部变量
    • 3、模块化
  • 二、性能提升
    • 1、使用fft调用shell
    • 2、不要在循环中拼接字符串
    • 3、不要频繁修改table
    • 4、不要在table中用nil
    • 5、做好异常处理
    • 6、ngx.var 的性能提升
  • 三、拓展
    • 1、加载字符串为动态方法

一、基础

1、常用

OpenResty 中文官网:https://openresty.org/cn/

包管理:https://opm.openresty.org/

(1)Lua 的下标从 1 开始

(2)使用 … 来拼接字符串

2、使用局部变量

在 Lua 中,变量默认是全局的,会被放到名为 _G 的 table 中。不加 local 的变量会在全局表中查找,这是昂贵的操作。如果再加上一些变量名的拼写错误,就会造成难以定位的 bug。

建议总是使用 local 来声明变量,即使在 require module 的时候也是一样:

-- Recommended  local xxx = require('xxx')   -- Avoid require('xxx')  local ngx_re = require "ngx.re" local ngx = require "ngx" 
--No local function foo()     local ok, err = ngx.timer.at(delay, handler) end  --Yes local timer_at = ngx.timer.at   local function foo()     local ok, err = timer_at(delay, handler) end 
-- 为了风格的统一,require 和 ngx 也需要 local 化: --No local core = require("apisix.core") local timer_at = ngx.timer.at   local function foo()     local ok, err = timer_at(delay, handler) end   --Yes local ngx = ngx local require = require local core = require("apisix.core") local timer_at = ngx.timer.at   local function foo()     local ok, err = timer_at(delay, handler) end 

3、模块化

-- hello.lua定义一个对象,并返回 local _M = {}   _M.color = {       red = 1,       blue = 2,       green = 3   }     return _M 
location / {     content_by_lua_block {     	-- 引入hello,并用一个变量接收,这个变量就可以调用对象的方法和变量了         local hello = require "hello"         ngx.say(hello.color.green)      } } 

二、性能提升

1、使用fft调用shell

-- 不要用阻塞的lua语法 os.execute("kill -HUP " .. pid)  os.execute(" cp test.exe /tmp ") os.execute(" openssl genrsa -des3 -out private.pem 2048 ")  -- 使用lua-resty-signal 这个 OpenResty 自带的库 local resty_signal = require "resty.signal" local pid = 12345 local ok, err = resty_signal.kill(pid, "KILL")  -- 使用基于 ngx.pipe 的 lua-resty-shell 库 $ resty -e 'local shell = require "resty.shell" local ok, stdout, stderr, reason, status =     shell.run([[echo "hello, world"]])     ngx.say(stdout) ' 

2、不要在循环中拼接字符串

-- 不要在循环中拼接字符串 $ resty -e 'local begin = ngx.now() local s = "" -- for 循环,使用 .. 进行字符串拼接 for i = 1, 100000 do     s = s .. "a" end ngx.update_time() print(ngx.now() - begin) '  -- 用table进行优化 $ resty -e 'local begin = ngx.now() local t = {} -- for 循环,使用数组来保存字符串,自己维护数组的长度 for i = 1, 100000 do     t[i] = "a" end local s =  table.concat(t, "") ngx.update_time() print(ngx.now() - begin) '  -- 或者自己定义数组索引 $ resty -e 'local begin = ngx.now() local t = {} local index = 1 for i = 1, 100000 do     t[index] = "a"     index = index + 1 end local response = table.concat(t, "") ngx.say(response) ' 

3、不要频繁修改table

-- 预先创建table,然后增删改,性能是很差的,原因在于每次新增和删除数组元素的时候,都会涉及到数组的空间分配、resize 和 rehash。 local t = {} local color = {first = "red", "blue", third = "green", "yellow"}  -- 如果涉及对table的频繁修改,考虑初始化table的容量,这样就不需要使用table.insert等方法,直接通过下标设置值即可 -- table.new(narray, nhash) 两个参数分别代表table里是array还是hash的  -- table.new(10, 0) 或者 table.new(0, 10) 这样的,后者是 hash 性质的 table local new_tab = require "table.new" local t = new_tab(100, 0) for i = 1, 100 do   t[i] = i end  -- 可以考虑对table进行重用 -- 用 table.new(narray, nhash) 生了一个长度为 100 的数组,clear 后,长度还是 100。 -- table.clear方法就是将table所有的内容设为了nil local ok, clear_tab = pcall(require, "table.clear")   if not ok then     clear_tab = function (tab)       for k, _ in pairs(tab) do         tab[k] = nil       end     end   end   

4、不要在table中用nil

-- 一定不要在数组中使用 nil: --No local t = {1, 2, nil, 3}  -- 如果一定要使用空值,请用 ngx.null 来表示: --Yes local t = {1, 2, ngx.null, 3} 

5、做好异常处理

对于有错误信息返回的函数,我们必须对错误信息进行判断和处理:

--No local sock = ngx.socket.tcp() local ok = sock:connect("www.baidu.com", 80) ngx.say("successfully connected to baidu!")  --Yes local sock = ngx.socket.tcp() localok, err = sock:connect("www.google.com", 80) if not ok then     ngx.say("failed to connect to google: ", err)     return end ngx.say("successfully connected to google!") 

而如果是自己编写的函数,错误信息要作为第二个参数,用字符串的格式返回:

--No local function foo()     local ok, err = func()     if not ok then         return false     end     return true end  --No local function foo()     local ok, err = func()     if not ok then         return false, {msg = err}     end     return true end  --Yes local function foo()     local ok, err = func()     if not ok then         return false, "failed to call func(): " .. err     end     return true end 

6、ngx.var 的性能提升

ngx.var 是一个性能损耗比较大的操作,在实际使用时,我们需要用 ngx.ctx 来做一层缓存

-- lua-var-nginx-module模块,性能比起ngx.var 提升了 5 倍。它采用的是 FFI 的方式,所以,你需要在编译 OpenResty 的时候,先加上编译选项 ./configure --prefix=/opt/openresty \          --add-module=/path/to/lua-var-nginx-module  -- 然后,使用 luarocks 的方式来安装 lua 库: luarocks install lua-resty-ngxvar  -- 这里调用的方法也很简单,只需要一行 fetch 函数的调用就可以了。它的效果完全等价于原有的 ngx.var.remote_addr,来获取到终端的 IP 地址: content_by_lua_block {     local var = require("resty.ngxvar")     ngx.say(var.fetch("remote_addr")) }  

三、拓展

1、加载字符串为动态方法

可以把 s 这个包含函数的字符串,改成可以由用户指定的形式,并加上执行它的条件,这样其实就是 FaaS 的原型了。

resty -e 'local s = [[  return function()     ngx.say("hello world") end ]] local  func1 = loadstring(s) local ret, func = pcall(func1) func()' 

相关内容

热门资讯

推出新举措!情怀莆仙脚本辅助器... 推出新举措!情怀莆仙脚本辅助器,小程序牵手跑得辅助,曝光教程(竟然真的是有挂)-哔哩哔哩1、让任何用...
这一现象值得深思!aapoke... 这一现象值得深思!aapoker辅助软件合法吗,天天辅助器透视,总是是有挂(专业软件教程)-哔哩哔哩...
科技通报!谁有老友广东辅助器(... 科技通报!谁有老友广东辅助器(辅助挂)开挂透视辅助软件(都是真的有挂)-哔哩哔哩亲,关键说明,谁有老...
据权威媒体报道!可可茶馆辅助工... 据权威媒体报道!可可茶馆辅助工具,蛮王辅助,AA德州教程(好像存在有挂)-哔哩哔哩1、点击下载安装,...
随着!智星菠萝辅助,打大a辅助... 随着!智星菠萝辅助,打大a辅助器,一贯真的是有挂(详情分享教程)-哔哩哔哩该软件可以轻松地帮助玩家将...
盘点一款!八闽状元郎胜必神器(... 盘点一款!八闽状元郎胜必神器(辅助挂)开挂透视辅助方法(确实有挂)-哔哩哔哩在进入八闽状元郎胜必神器...
此事引发广泛关注!同城游辅助工... 此事引发广泛关注!同城游辅助工具,途游辅助软件网站,教你攻略(其实真的有挂)-哔哩哔哩1、上手简单,...
有玩家发现!竞技联盟辅助插件,... 有玩家发现!竞技联盟辅助插件,兴动互娱辅助工具,确实真的有挂(总结揭秘教程)-哔哩哔哩小薇(透视辅助...
最终!玩吧辅助器,黑科技辅助软... 最终!玩吧辅助器,黑科技辅助软件免费,软件教程(一直真的有挂)-哔哩哔哩运黑科技辅助软件免费辅助工具...
重大通报!闲逸有没有辅助软件功... 重大通报!闲逸有没有辅助软件功能(辅助挂)开挂透视辅助方法(原来真的有挂)-哔哩哔哩;1、下载好闲逸...