由于独立秒杀目前接过来了,但是其核心是利用openresty实现的,本人对此技术栈较为陌生,特写下本篇指导,以期快速上手。

一、openresty入门初步

安装openresty

首先是安装openresty,macOS的安装方式

brew tap openresty/brew
brew install openresty

安装完毕之后,可以得到安装路径,配置到系统PATH中并生效:

export PATH=/usr/local/Cellar/openresty/1.21.4.1_2/nginx/sbin:$PATH

之后就可以校验是否安装成功了,按照如下命令检测:

which nginx

结果显示如下的路径:/usr/local/Cellar/openresty/1.21.4.1_2/nginx/sbin/nginx,则证明安装成功;如果没有任何输出,则表明未安装成功,可以检查安装路径是否正确。

初步使用

新建个文件夹,然后利用如下命令新建conf,logs两个字文件夹:

mkdir conf logs

之后,进行nginx配置文件配置,运行命令如下:

nano conf/nginx.conf

输入内容如下:

worker_processes  1;
error_log logs/error.log;
events {
    worker_connections 1024;
}
http {
    server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua_block {
                ngx.say("<p>hello, world</p>")
            }
        }
    }
}

写完之后,可以测试脚本是否正常:

openresty -p $PWD/ -c conf/nginx.conf -t

之后在当前目录启动即可:

openresty -p $PWD/ -c conf/nginx.conf

利用如下命令可以看到启动的master,worker进程

ps aux|grep nginx|grep -v /tmp/ 

这里需要注意下,一些常用的openresty命令如下

(1) 启动 openresty
(2) 重启 openresty -s reload
(3) 关闭 openresty -s stop

浏览器中输入 http://127.0.0.1:8080就可以看到正常的输出结果了。

 

二、简单的lua脚本

创建新的文件夹,名称分别为 log,conf, lua,命令如下:

mkdir logs conf lua

nginx.conf文件内容如下:

worker_processes  1;
error_log logs/error.log;
events {
    worker_connections 1024;
}
http {
    server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua_file /Users/shichaoyang/openresty/hello-module/lua/hello.lua;
        }
    }
}

可以看到,这里利用content_by_lua_file命令来制定lua脚本文件。其中hello.lua的内容为 :

ngx.say("hello lua");

之后在当前目录启动即可:

openresty -p $PWD/ -c conf/nginx.conf

在浏览器访问,即可以看到正确的输出结果了。

 

三、lua脚本模块

同样创建logs,conf,lua文件夹,其中nginx.conf文件内容如下:

worker_processes 1;
error_log logs/error.log;


events {
    worker_connections 1024;
}


http {
    lua_package_path "/usr/local/Cellar/openresty/1.21.4.1_2/?.lua;;$prefix/lua/?.lua;";


    server {
        listen 8081 reuseport;


        location / {
            default_type text/plain;
            content_by_lua_block {
                local hello = require "mod"
                hello.greet("a lua module");
            }
        }
    }
}

脚本内容如下:


local _M = {}


function _M.greet(name)
    ngx.say("hello from name ",name)
end


return _M

之后在当前目录启动即可:

 openresty -p $PWD/ -c conf/nginx.conf

可以看到,脚本模块的封装方式。这里需要说明下,nginx启动的时候会从lua_package_path指定的路径中将lua文件加载进来。而content_by_lua_block则可以指定执行的业务逻辑代码。

这里也许有人要问,为什么把openresty按住根目录下的lua文件都加载进来呢,主要原因是因为模块的执行需要resty.core的支持,如果不加入usr/local/Cellar/openresty/1.21.4.1_2/?.lua;; 报错:

ginx: [alert] failed to load the 'resty.core' module (https://github.com/openresty/lua-resty-core); ensure you are using an OpenResty release from https://openresty.org/en/download.html (reason: module 'resty.core' not found:

no field package.preload['resty.core']

所以这里需要将lua_package_path改成 lua_package_path "$prefix/lua/?.lua;/usr/local/lib/lua/?.lua;;";

参见:https://github.com/openresty/lua-nginx-module/issues/1533

 

四、lua脚本传参

本指导来源于chatGPT回答:

我:openresty多模块之间传参,写一个在两个网页中传参的代码示例
ChatGPT:
以下是一个在两个页面之间传参的OpenResty代码示例:
location /page1 { 
  content_by_lua_block {
        local param1 = ngx.var.arg_param1
        local param2 = ngx.var.arg_param2
        ngx.redirect("/page2?param1=" .. param1 .. "& param2=" .. param2)
    }
}


location /page2 { 
   content_by_lua_block { 
      local param1 = ngx.var.arg_param1 
      local param2 = ngx.var.arg_param2
      -- Do something with the two parameters here
    }
}

这里我们就根据其指导来实现一下。

同样的,创建logs,conf,lua文件夹,然后nginx.conf内容如下:

worker_processes  1;
error_log logs/error.log;


events {
    worker_connections 1024;
}


http {
    server {
        listen 8080;


        location /p1 {
            default_type text/html;
            content_by_lua_file /Users/shichaoyang/openresty/trans-module/lua/p1.lua;
        }


         location /p2 {
            default_type text/html;
            content_by_lua_file /Users/shichaoyang/openresty/trans-module/lua/p2.lua;
        }
    }
}

lua脚本p1内容如下:

local param1 = ngx.var.arg_param1
local param2 = ngx.var.arg_param2


ngx.redirect("/p2?param1=" .. param1 .. "& param2=" .. param2)

lua脚本p2内容如下:

local param1 = ngx.var.arg_param1
local param2 = ngx.var.arg_param2


ngx.say(param1)
ngx.say(param2)

之后在当前目录启动即可:

openresty -p $PWD/ -c conf/nginx.conf

之后访问:

http://127.0.0.1:8080/p1?param1=1& param2=2

则会自动跳转到

http://127.0.0.1:8080/p2?param1=1& param2=2

并输出1 2

更多内容请访问:https://openresty-reference.readthedocs.io/en/latest/Lua_Nginx_API/

 

五、lua脚本调试

同样的,创建logs,conf,lua文件夹,然后nginx.conf内容如下:

worker_processes  1;
error_log logs/error.log;


events {
    worker_connections 1024;
}


http {

    lua_package_path "/usr/local/Cellar/openresty/1.21.4.1_2/?.lua;;$prefix/lua/?.lua;";


    server {
        listen 8080;

        location / {
            default_type text/html;
            content_by_lua_file /Users/shichaoyang/openresty/ut-module/lua/ut.lua;
        }


         location /test {
            content_by_lua_file  /Users/shichaoyang/openresty/ut-module/lua/uttest.lua;
        }


    }
}

ut.lua脚本内容如下:

ngx.say("111")

uttest.lua脚本内容如下:



local iresty_test    = require "iresty_test"
local tb = iresty_test.new({unit_name="example"})


function tb:init(  )
    self:log("init complete")
end


function tb:test_00001(  )
    error("invalid input")
end


function tb:atest_00002()
    self:log("never be called")
end


function tb:test_00003(  )
   self:log("ok")
end


-- units test
tb:run()

这里需要从https://github.com/iresty/lua-resty-test/blob/master/lib/resty/iresty_test.lua将此文件下载,并放到lua文件夹下面

之后在当前目录启动即可:

openresty -p $PWD/ -c conf/nginx.conf

访问:http://127.0.0.1:8080/test 即可得到测试结果:

0.000 [example] unit test start

0.000 [example] init complete

0.000  \_[test_00001] fail /Users/shichaoyang/openresty/ut-module/lua/uttest.lua:9: invalid input

0.000  \_[test_00003] 鈫搊k

0.000  \_[test_00003] PASS

0.000 [example] unit test complete



 

六、openresty配置必知必会

1. proxy_pass, 反向代理,是指以代理服务器接收Internet上的链接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给Internet上请求连接的客户端。

举个例子,比如我的内部服务器是放在212环境上,那么开发的接口如下这样的:

http://192.168.1.212:8136/xxxx 然后端口号是8136,然后直接访问该接口会返回对应的数据,但是接口一般都是域名访问的,因此我们需要在nginx上配置一个域名,假如为 xy.xxx.com, 然后当我们在联调接口的时候,我们使用 http://xy.xxx.com/xxxx 这样的接口时,它会反向代理到 http://192.168.1.212:8136/xxxx 上来,这样它会返回内部服务器的数据给客户端,客户端就拿到对应的数据显示出来了。

2. resolver , DNS解析,一般配制成公共的或者公司内部的都行。

3. allow & denyallow 和 deny 指令在 ngx_http_access_module 模块中,两个指令分别表示允许或禁止源 IP 访问,用于对源 IP 做访问控制,nginx 是按照自上而下的顺序进行匹配,匹配到一个就不往下继续了。

allow 指令

a、允许哪些 IP 访问,all 表示允许所有;

b、作用域 http / server / location / limit_except ;

deny 指令

a、禁止哪些 IP 访问,all 表示禁止所有;

b、作用域 http / server / location / limit_except ;

	location = /request_stat {
                        allow 192.168.0.0/16;
                        deny all;
                        request_status on;
                }

4. stub_status, stub_status模块参数可以用来查看Nginx的一些状态信息如连接数、请求数统计等,需要安装好相应的模块stub_status才支持配置,安装时需要指定–with-http_stub_status_module。参考: https://blog.csdn.net/jxlhljh/article/details/126270472

	location = /status {
		allow 192.168.0.0/16;
		deny all;
		stub_status on;
		access_log off;
	}

5. access_log, 日志文件一般存放在 /var/log/nginx 下,若是docker启动则可以使用主机挂载位置,直接使用 tail -f命令即可查看access日志。参考: https://blog.csdn.net/weixin_45698637/article/details/128486012

6. set指令, set 指令是用于定义一个变量,并且赋值。这些变量值可以通过ngx.arg.xxx在lua文件内部使用。

	    #black list redis
		set $risk_control_server "127.0.0.1";
		set $risk_control_port 6380;

7. log_by_lua, log_by_lua*​ 是一个请求经历的最后阶段。由于记日志跟应答内容无关,Nginx 通常在结束请求之后才更新访问日志。由此可见,如果我们有日志输出的情况,最好统一到 ​log_by_lua* ​阶段。如果我们把记日志的操作放在 ​content_by_lua*​ 阶段,那么将线性的增加请求处理时间。 api文档参考: https://www.kancloud.cn/qq13867685/openresty-api-cn/159199

8. localtion @命名location,用@标识,类似于定于goto语句块。


                location  @item_fail {
                        default_type application/json;
                        content_by_lua_file /export/runtime/WEB-INF/classes/new_lua/item_fail.lua;
                }

                error_page 404 @item_fail;
                error_page 500 502 503 504 @item_fail;

9. limit_req & limit_req_zone, 限流,基于漏桶算法实现的。

limit_req_zone $binary_remote_addr zone=perip_rps:10m rate=5r/s; #单ip每秒限制5个请求
limit_req_zone $server_name zone=perserver_rps:10m rate=3000r/s; #每个server每秒限制处理3000个请求

上面分别是按照ip和server来限流rps,zone=perip_rps:10m是设定这个limit_req_zone的名字为perid_rps,且在nginx内存里分配10m的空间来存储访问频次信息,rate=15r/s表示每秒15个请求,30r/m每分钟30次请求。

一般在http里配置好了limit_req_zone之后,就可以在server或者location里边配置limit_req了,比如:

limit_req zone=perserver_rps burst=2000 nodelay;  #server每秒请求限流
limit_req zone=perip_rps burst=10 nodelay; #每个ip每秒请求如果超过limit_req_zone的配置,最多可以缓冲10个

这里设置 brust=10,表示在超过限制速率 5r/s 的时候,同时至多允许额外有 10 个请求排队等候,待平均速率回归正常后,队列前面的请求会优先被处理。

参考: http://events.jianshu.io/p/9db107f579a5

参考: https://www.upyun.com/opentalk/opentalk/417.html

参考: https://www.w3cschool.cn/openresty1/

 

七、openresty脚本必知必会

posted on 2023-03-22 09:58  程序诗人  阅读(383)  评论(0编辑  收藏  举报