【Nginx高级篇】Lua基础语法和OpenResty的安装

news2024/12/25 11:18:51

目录

一、前言

二、Lua基础语法  

hello world

保留关键字

注释

变量

字符串

空值

布尔类型

作用域

控制语句

if-else

for循环

函数

赋值

返回值 

Table

数组

遍历

成员函数

三、openresty的安装

(一)预编译安装

(二)源码编译安装

(三)服务命令

(四)测试lua脚本以文件的形式

代码热部署

获取nginx请求头信息

获取post请求参数

Http协议版本

请求方法

原始的请求头内容

body内容体

(五)Nginx缓存

Nginx全局内存缓存

lua-resty-lrucache

lua-resty-redis访问redis

lua-resty-mysql


一、前言

Lua 是由巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组于1993年开发的一种轻量、小巧的脚本语言,用标准 C 语言编写,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

官网:The Programming Language Lua

学习lua语言之前需要先安装lua版本,并在ideal下载插件,具体的可以看下面这篇文章

Lua环境安装+Idea配置_idea配置lua_xiaowu714的博客-CSDN博客https://blog.csdn.net/xiaowu714/article/details/127763087?spm=1001.2014.3001.5506

二、Lua基础语法  

hello world

在ideal新建lua项目并创建lua文件后输入以下内容

local function main()
    print("Hello world!")
end

main()

运行结果

保留关键字

and break do else elseif end false for function 
if in local nil not or repeat return then true 
until while

注释

-- 两个减号是行注释

--[[

 这是块注释

 这是块注释.

 --]]

变量

数字类型

Lua的数字只有double型,64bits

你可以以如下的方式表示数字

num = 1024​

num = 3.0​

num = 3.1416

​num = 314.16e-2

​num = 0.31416E1

​num = 0xff​

num = 0x56

字符串

可以用单引号,也可以用双引号

也可以使用转义字符‘\n’ (换行), ‘\r’ (回车), ‘\t’ (横向制表), ‘\v’ (纵向制表), ‘\’ (反斜杠), ‘\”‘ (双引号), 以及 ‘\” (单引号)等等

下面的四种方式定义了完全相同的字符串(其中的两个中括号可以用于定义有换行的字符串)

a = 'alo\n123"'

a = "alo\n123\""

a = '\97lo\10\04923"'

a = [[alo

123"]]

空值

C语言中的NULL在Lua中是nil,比如你访问一个没有声明过的变量,就是nil

布尔类型

只有nil和false是 false

数字0,‘’空字符串(’\0’)都是true

作用域

lua中的变量如果没有特殊说明,全是全局变量,那怕是语句块或是函数里。

变量前加local关键字的是局部变量。

控制语句

while循环

local function main()

    local i = 0
    local max = 10
    while i <= max do
        print(i)
        i = i + 1
    end
end

main()

运行结果

if-else

local function main()

    local age = 30

    local sex = 'Malee'

    if age <= 40 and sex == "Male" then
        print("男人四十一枝花")
    elseif age > 40 and sex ~= "Female" then -- ~=  等于 !=
        io.write("old man")
    elseif age < 20 then
        print("too young too simple")
    else
        print("Your age is "..age)   --Lua中字符串的连接用..

    end

end

main()

for循环

local function main()

    for i = 10, 1 , -1 do   -- i<=1, i--
        print(i)
    end
    for i = 1, 10 , 1 do    -- i<=10, i++
        print(i)
    end

end

main()

函数

local function main()

    function myPower(x,y) -- 定义函数

        return      y+x

    end

    power2 = myPower(2,3)  -- 调用

    print(power2)
end

main()
local function main()

    function newCounter()

        local i = 0
        return function()     -- anonymous function(匿名函数)

            i = i + 1

            return i

        end
    end



    c1 = newCounter()

    print(c1())  --> 1

    print(c1())  --> 2

    print(c1())
end

main()

赋值

local function main()
    name, age,bGay = "yiming", 37, false, "yimingl@hotmail.com" -- 多出来的舍弃

    print(name,age,bGay)
end

main()

返回值 

local function main()
    function isMyGirl(name)
        return name == 'xiao6' , name
    end

    local bol,name = isMyGirl('xiao6')

    print(name,bol)
end

main()

 

Table

KV形式,类似map

local function main()
    dog = {name='111',age=18,height=165.5}

    dog.age=35

    print(dog.name,dog.age,dog.height)

    print(dog)

end

main()

数组

local function main()
    local function main()
        arr = {"string", 100, "dog",function() print("wangwang!") return 1 end}

        print(arr[4]())
    end
    main()
end

main()

遍历

local function main()
    arr = {"string", 100, "dog",function() print("wangwang!") return 1 end}

    for k, v in pairs(arr) do

        print(k, v)
    end
end

main()

成员函数

local function main()

person = {name='旺财',age = 18}

  function  person.eat(food)

    print(person.name .." eating "..food)

  end
person.eat("骨头")
end
main()

三、openresty的安装

(一)预编译安装

以CentOS举例 其他系统参照:OpenResty - OpenResty® Linux 包

你可以在你的 CentOS 系统中添加 openresty 仓库,这样就可以便于未来安装或更新我们的软件包(通过 yum update 命令)。运行下面的命令就可以添加我们的仓库:

 yum install yum-utils

 yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo

然后就可以像下面这样安装软件包,比如 openresty:

 yum install openresty

如果你想安装命令行工具 resty,那么可以像下面这样安装 openresty-resty 包:

 sudo yum install openresty-resty

(二)源码编译安装

官网下载tar.gz包

OpenResty - 下载

最小版本基于nginx1.21

./configure

然后在进入 openresty-VERSION/目录, 然后输入以下命令配置:

./configure

默认, --prefix=/usr/local/openresty 程序会被安装到/usr/local/openresty目录。

依赖 gcc openssl-devel pcre-devel zlib-devel

安装:yum install gcc openssl-devel pcre-devel zlib-devel postgresql-devel

您可以指定各种选项,比如

./configure --prefix=/opt/openresty \

            --with-luajit \

            --without-http_redis2_module \

            --with-http_iconv_module \

            --with-http_postgres_module

试着使用 ./configure --help 查看更多的选项。

make && make install

查看openresty的目录

(三)服务命令

启动

Service openresty start

停止

Service openresty stop

检查配置文件是否正确

Nginx -t

重新加载配置文件

Service openresty reload

查看已安装模块和版本号

Nginx -V

测试Lua脚本

在Nginx.conf 中写入
   location /lua {

        default_type text/html;
        content_by_lua '
           ngx.say("<p>Hello, World!</p>")
         ';
      }

启动nginx

./nginx -c /usr/local/openresty/nginx/conf/nginx.conf

(四)测试lua脚本以文件的形式


       location /lua {

        default_type text/html;
        content_by_lua_file lua/hello.lua;
      }

 在nginx目录下创建lua目录并写入hello.lua文件,文件内容

ngx.say("<p>hello world!!!</p>")

代码热部署

hello.lua脚本每次修改都需要重启nginx,很繁琐,因此可以通过配置开启热部署

 lua_code_cache off;

 会提示开启该功能可能影响nginx的性能

获取nginx请求头信息

local headers = ngx.req.get_headers()                         

ngx.say("Host : ", headers["Host"], "<br/>")  

ngx.say("user-agent : ", headers["user-agent"], "<br/>")  

ngx.say("user-agent : ", headers.user_agent, "<br/>")

for k,v in pairs(headers) do  

    if type(v) == "table" then  

        ngx.say(k, " : ", table.concat(v, ","), "<br/>")  

    else  

        ngx.say(k, " : ", v, "<br/>")  

    end  

end  

 

获取post请求参数

ngx.req.read_body()  

ngx.say("post args begin", "<br/>")  

local post_args = ngx.req.get_post_args()  

for k, v in pairs(post_args) do  

    if type(v) == "table" then  

        ngx.say(k, " : ", table.concat(v, ", "), "<br/>")  

    else  

        ngx.say(k, ": ", v, "<br/>")  

    end  
end

 

Http协议版本

ngx.say("ngx.req.http_version : ", ngx.req.http_version(), "<br/>")

请求方法

ngx.say("ngx.req.get_method : ", ngx.req.get_method(), "<br/>")  

原始的请求头内容

ngx.say("ngx.req.raw_header : ",  ngx.req.raw_header(), "<br/>")  

body内容体

ngx.say("ngx.req.get_body_data() : ", ngx.req.get_body_data(), "<br/>")

(五)Nginx缓存

Nginx全局内存缓存

nginx配置文件的http块中添加

lua_shared_dict shared_data 1m; # 申请一兆内存作为内存缓存,该内存可以被所有的进程进行共享的且可以保持原子性

hello.lua脚本内容

local shared_data = ngx.shared.shared_data  

  

local i = shared_data:get("i")  

if not i then  

    i = 1  

    shared_data:set("i", i)  

    ngx.say("lazy set i ", i, "<br/>")  
end  
 

i = shared_data:incr("i", 1)  

ngx.say("i=", i, "<br/>")

接下来每次都会从访问ii都会+1

lua-resty-lrucache

Lua 实现的一个简单的 LRU 缓存,适合在 Lua 空间里直接缓存较为复杂的 Lua 数据结构:它相比 ngx_lua 共享内存字典可以省去较昂贵的序列化操作,相比 memcached 这样的外部服务又能省去较昂贵的 socket 操作

https://github.com/openresty/lua-resty-lrucache

引用lua文件

       location /lua {

        default_type text/html;
#        content_by_lua_file lua/hello.lua;

            content_by_lua_block {
                require("my/cache").go()
            }
      }

当不知道nginx是在哪个文件下查找时可以先重启nginx,然后访问报错试一下,然后在error.log文件中可以看到默认在哪些文件下查找

我们在lualib下创建my目录,并在my目录下创建cache.lua脚本,脚本内容如下:

local _M = {}


lrucache = require "resty.lrucache"

c, err = lrucache.new(200)  -- allow up to 200 items in the cache
ngx.say("count=init")


if not c then
    error("failed to create the cache: " .. (err or "unknown"))
end

function _M.go()

count = c:get("count")


c:set("count",100)
ngx.say("count=", count, " --<br/>")


if not count then  


    c:set("count",1)

    ngx.say("lazy set count ", c:get("count"), "<br/>")  

else


c:set("count",count+1)
 


ngx.say("count=", count, "<br/>")
end


end
return _M

记得开启lua_code_cache,即代码缓存,不然每次代码都会重复执行,永远都拿不到count的值

lua-resty-redis访问redis

官网:GitHub - openresty/lua-resty-redis: Lua redis client driver for the ngx_lua based on the cosocket API

常用方法

local res, err = red:get("key")

local res, err = red:lrange("nokey", 0, 1)

ngx.say("res:",cjson.encode(res))

创建连接

red, err = redis:new()

ok, err = red:connect(host, port, options_table?)

timeout

red:set_timeout(time)

keepalive

red:set_keepalive(max_idle_timeout, pool_size)

close

ok, err = red:close()

pipeline

red:init_pipeline()

results, err = red:commit_pipeline()

认证

    local res, err = red:auth("foobared")

    if not res then

        ngx.say("failed to authenticate: ", err)

        return
end

nginx的配置

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    lua_code_cache off;
    lua_shared_dict shared_data 1m;
    server {
        listen       888;
        server_name  localhost;

       location /lua {

        default_type text/html;
        content_by_lua_file lua/redis.lua;

        }
        location / {
            root   html;
            index  index.html index.htm;
        }


        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

redis.lua脚本

  local redis = require "resty.redis"
                local red = redis:new()

                red:set_timeouts(1000, 1000, 1000) -- 1 sec

  local ok, err = red:connect("127.0.0.1", 6379)
  local res, err = red:auth("zjy123...000")

    if not res then

        ngx.say("failed to authenticate: ", err)

        return
  end
 if not ok then
                    ngx.say("failed to connect: ", err)
                    return
                end

                ok, err = red:set("dog", "an animal")
                if not ok then
                    ngx.say("failed to set dog: ", err)
                    return
                end

                ngx.say("set result: ", ok)

                local res, err = red:get("dog")
                if not res then
                    ngx.say("failed to get dog: ", err)
                    return
                end

                if res == ngx.null then
                    ngx.say("dog not found.")
                    return
                end


              ngx.say("dog: ", res)

访问结果

 验证

总结

lua-resty-redis直接访问redis可以节省原本的一些步骤,比如:

客户端请求--nginx--tomcat--redis--tomcat--nginx--客户端

优化为:

客户端请求--nginx--redis--nginx--客户端

对于一些不常更新的放在redis的资源可以使用该方式,节省了不必要的步骤

lua-resty-mysql

官网: GitHub - openresty/lua-resty-mysql: Nonblocking Lua MySQL driver library for ngx_lua or OpenResty

配置文件

    charset utf-8;
    lua_code_cache off;
    lua_shared_dict shared_data 1m;
    server {
        listen       888;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;


       location /lua {

        default_type text/html;
        content_by_lua_file lua/mysql.lua;

       }
    }

 mysql.lua

local mysql = require "resty.mysql"
                local db, err = mysql:new()
                if not db then
                    ngx.say("failed to instantiate mysql: ", err)
                    return
                end

                db:set_timeout(1000) -- 1 sec


                local ok, err, errcode, sqlstate = db:connect{
                    host = "192.168.102.100",
                    port = 3306,
                    database = "atguigudb1",
                    user = "root",
                    password = "123456",
                    charset = "utf8",
                    max_packet_size = 1024 * 1024,
                }


                ngx.say("connected to mysql.<br>")



                local res, err, errcode, sqlstate = db:query("drop table if exists cats")
                if not res then
                    ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
                    return
                end


                res, err, errcode, sqlstate =
                    db:query("create table cats "
                             .. "(id serial primary key, "
                             .. "name varchar(5))")
                if not res then
                    ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
                    return
                end

                ngx.say("table cats created.")



                res, err, errcode, sqlstate =
                    db:query("select * from student")
                if not res then
                    ngx.say("bad result: ", err, ": ", errcode, ": ", sqlstate, ".")
                    return
                end

                local cjson = require "cjson"
                ngx.say("result: ", cjson.encode(res))


                local ok, err = db:set_keepalive(10000, 100)
                if not ok then
                    ngx.say("failed to set keepalive: ", err)
                    return
                end
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/526959.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VMware中Ubuntu拓展磁盘容量的两种方式 图形化方式命令行磁盘分区方式(亲测有效简单且详细)linux磁盘分区

文章目录 前言1. 软件设置扩容2. 容量查看3. 容量拓展实现3.1 图形化容量拓展分配3.2 磁盘命令行方式拓展容量3.2.1 确定磁盘挂载目录3.2.2 系统磁盘扩容 4. 分盘扩容TIPS&#xff1a;总结&#xff1a; 前言 在用VMware虚拟机的情况下&#xff0c;一开始分配的容量在使用过程中…

PMP项目管理-[第十二章]采购管理

采购管理知识体系&#xff1a; 规划采购管理&#xff1a; 实施采购&#xff1a; 控制采购&#xff1a; 12.1 规划采购管理 定义&#xff1a;记录项目采购决策、明确采购方法、识别潜在卖方的过程 作用&#xff1a;确定是否从项目外部获取货物或服务.如果是&#xff0c;则还要确…

循环结构程序设计

一、循环结构语句 C语言提供了三种循环语句&#xff08;for语句&#xff09;、while语句和do-while语句。 for语句&#xff1a; for(表达式1 &#xff1b; 表达式2 &#xff1b; 表达式3) {   循环体语句&#xff1b; } for语句的执行过程&#xff1a; 首先计算表达式1。判断…

【LED子系统】五、核心层详解(二)

个人主页&#xff1a;董哥聊技术 我是董哥&#xff0c;高级嵌入式软件开发工程师&#xff0c;从事嵌入式Linux驱动开发和系统开发&#xff0c;曾就职于世界500强公司&#xff01; 创作理念&#xff1a;专注分享高质量嵌入式文章&#xff0c;让大家读有所得&#xff01; 文章目录…

基于B/S架构、可替代付费商业软件的一站式量化交易平台

产品简介 这是一个面向程序员的量化交易软件&#xff0c;用于期货、股票、外汇、炒币等多种交易场景&#xff0c;实现自动交易。已对接了CTP接口&#xff08;国内期货&#xff09;、老虎证券接口&#xff08;美股港股&#xff09;。 功能特性&#xff1a; 一站式平台&#x…

Protell99SE祭文

Protell99SE祭文 大概是在21年前的今天&#xff0c;我和你结合在一起&#xff0c;陪伴走过无数的设计。 我的感觉&#xff0c;大概是在2021年吧&#xff0c;你逐渐离我远去。啊&#xff0c;Protel99SE时代一去不复返了。 我用了你21年&#xff0c;虽着AD软件的到来&#xff…

【C++】19.C++11

1.C11 auto 范围for 新容器 线程库列表初始化右值引用和移动语义 lambda表达式容器支持花括号列表初始化 本质是增加一个initializer_list的构造函数initializer_list支持花括号 2.列表初始化 #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include <ve…

​数字化转型升级之工业元宇宙与AIGC

月説小飞象交流会 生活就是&#xff0c;面对复杂&#xff0c;保持欢喜。心烦时&#xff0c;记住三句话&#xff1a;1、算了吧。2、没关系。3、会过去的。 内部交流│24期 数字化转型升级 工业元宇宙与AIGC data analysis ●●●● 分享人&#xff1a;李铁军 ‍ 现如今数字化不再…

定风波、渡重山、至未来:2023中国数字能源生态大会开启的新旅程

全球碳中和的时代背景下&#xff0c;面向3060发展目标&#xff0c;新使命、新技术、新应用的到来&#xff0c;都给能源产业带来了持续变革的必要性与可能性。 2023年5月11日&#xff0c;在2023中国数字能源生态大会上&#xff0c;华为数字能源技术有限公司总裁侯金龙发表了“融…

【微电网】含风、光、储联合发电的微电网优化调度研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

2023 年 IntelliJ IDEA 下载安装教程,超详细图文教程,亲测可用

. IDEA 下载 1、打开浏览器输入https://www.jetbrains.com/&#xff0c;进入 Jetbrains官网&#xff0c;点击 Developer Tools&#xff0c;再点击 Intellij IDEA 2、点击中间的 Download&#xff0c;进入IDEA下载界面 3、选择左边的 Ultimate 版本进行下载安装。Ultimate 版…

心法利器[84] | 最近面试小结

心法利器 本栏目主要和大家一起讨论近期自己学习的心得和体会&#xff0c;与大家一起成长。具体介绍&#xff1a;仓颉专项&#xff1a;飞机大炮我都会&#xff0c;利器心法我还有。 2022年新一版的文章合集已经发布&#xff0c;累计已经60w字了&#xff0c;获取方式看这里&…

让Chat-GPT成为你的微信小助理

前言 最近公司裁员风波&#xff0c;很不幸成为了裁员名单中的一员&#xff1b;此时又恰逢一波AIGC浪潮&#xff0c;首当其冲的就是GPT这样的大语言模型的诞生&#xff0c;是整个AI领域的一个质的飞跃。正好在这样一个空挡期&#xff0c;我就基于Chat-GPT 做了一些深入的实践&a…

ChatGPT是什么?

ChatGPT是什么&#xff1f; ChatGPT是一个基于人工智能技术的聊天机器人平台&#xff0c;旨在为用户提供智能化、高效率的交互体验。ChatGPT能够理解用户输入的自然语言&#xff0c;根据语义分析和机器学习算法生成相应的回答。它可以回答用户的问题、提供建议、进行闲聊等&am…

前端技术搭建井字游戏(内含源码)

The sand accumulates to form a pagoda ✨ 写在前面✨ 功能介绍✨ 页面搭建✨ 样式设置✨ 逻辑部分 ✨ 写在前面 上周我们实通过前端基础实现了飞机大战游戏&#xff0c;今天还是继续按照我们原定的节奏来带领大家完成一个井字游戏游戏&#xff0c;功能也比较简单简单&#x…

路径规划 | 图解快速随机扩展树RRT算法(附ROS C++/Python/Matlab仿真)

目录 0 专栏介绍1 什么是RRT算法&#xff1f;2 图解RRT算法原理3 算法仿真与实现3.1 ROS C实现3.2 Python实现3.3 Matlab实现 0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详细介绍全局规划(图搜索、采样法、…

〖Python网络爬虫实战㉕〗- Ajax数据爬取之Ajax 案例实战

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000 python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 说明&#xff1a;本专栏持续更新中&#xff0c;目前专栏免费订阅&#xff0c;在转为付费专栏前订阅本专栏的&#xff0c;可以免费订阅付…

Gradle下载、安装、配置

1. Gradle下载 1.1 Gradle下载地址&#xff1a;https://docs.gradle.org/current/userguide/installation.html#installing_manually 1.2 点击Download 1.3 选择想要下载的版本&#xff0c;点击binary-only即可下载 2. Gradle安装&#xff08;注意&#xff1a;安装gradle之前…

【C语言】三子棋小游戏的思路及实现(内附代码)

简单不先于复杂&#xff0c;而是在复杂之后。 目录 1. 分文件实现 2.分步骤实现 2.1 游戏菜单 2.2 创建棋盘 2.3 初始化棋盘 2.4 打印棋盘 2.5 玩家下棋 2.6 电脑下棋 2.7 判断输赢 3. 附完整代码 3.1 test.c 3.2 game.h 3.2 game.c 1. 分文件实现 当我…

对称加密、非对称加密、数字签名、消息摘要的简单学习

对称加密、非对称加密、数字签名、消息摘要的简单学习 前言对称加密算法DES特点&#xff1a;为什么不使用&#xff1a; 3DES&#xff08;Triple DES 或者 DESede&#xff09;特点&#xff1a;使用场景&#xff1a;为什么不用&#xff1a; AES&#xff08;Advanced Encryption S…