6.OpenResty系列之深入理解(二)

news2025/4/3 17:11:18
1. 日志输出
vim /usr/local/openresty/nginx/conf/nginx.conf

默认配置如下

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

http {
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

我们访问error.log,内容如下:

access.log,内容如下

# $remote_addr - 表示客户端发起请求的IP地址
# $remote_user - 表示发起请求的经过身份验证的用户的用户名(如果有)
# $time_local - 表示请求发起的本地时间
# $request - 表示客户端发起的HTTP请求,包括方法、URL和HTTP版本
# $status - 表示服务器返回的请求的HTTP状态码
# $body_bytes_sent - 表示服务器在响应体中发送的字节数
# $http_referer - 表示HTTP Referer头,指示引导客户端访问当前页面的页面的URL
# $http_user_agent - 表示客户端的Web浏览器或其他HTTP客户端的用户代理字符串
# $http_x_forwarded_for - 表示X-Forwarded-For头,通常用于跟踪客户端通过代理或负载均衡器连接到Web服务器时的原始IP地址
127.0.0.1 - - [07/Jan/2024:06:13:31 +0800] "GET login.cgi HTTP/1.1" 400 163 "-" "-"

如果你的日志需要归集,并且对时效性要求比较高那么用 lua-resty-logger-socket

lua-resty-logger-socket的目标是替代 Nginx 标准的 ngx_http_log_module 以非阻塞 IO 方式推送 access log 到远程服务器上。对远程服务器的要求是支持 syslog-ng 的日志服务

2. 子查询

Nginx 子请求是一种非常强有力的方式,它可以发起非阻塞的内部请求访问目标 location

需要注意的是,子请求只是模拟 HTTP 接口的形式, 没有 额外的 HTTP/TCP 流量,也 没有 IPC (进程间通信) 调用。所有工作在内部高效地在 C 语言级别完成

子请求与 HTTP 301/302 重定向指令 (通过 ngx.redirect) 完全不同,也与内部重定向 ((通过 ngx.exec) 完全不同

在发起子请求前,用户程序应总是读取完整的 HTTP 请求体 (通过调用 ngx.req.read_body 或设置 lua_need_request_body 指令为 on).

该 API 方法(ngx.location.capture_multi 也一样)总是缓冲整个请求体到内存中。因此,当需要处理一个大的子请求响应,用户程序应使用 cosockets 进行流式处理

下面是一个简单例子:

res = ngx.location.capture(uri)
  • 返回一个包含四个元素的 Lua 表 (res.status, res.header, res.body, 和 res.truncated)。
  • res.status (状态) 保存子请求的响应状态码。
  • res.header (头) 用一个标准 Lua 表储子请求响应的所有头信息。如果是“多值”响应头,这些值将使用 Lua (数组) 表顺序存储。例如,如果子请求响应头包含下面的行,则 res.header[“Set-Cookie”] 将存储 Lua 表 {“a=3”, “foo=bar”, “baz=blah”}。
 Set-Cookie: a=3
 Set-Cookie: foo=bar
 Set-Cookie: baz=blah

  • res.body (体) 保存子请求的响应体数据,它可能被截断。用户需要检测 res.truncated (截断) 布尔值标记来判断 res.body 是否包含截断的数据。这种数据截断的原因只可能是因为子请求发生了不可恢复的错误,例如远端在发送响应体时过早中断了连接,或子请求在接收远端响应体时超时
3. 不同阶段共享变量

在 OpenResty 的体系中,可以通过共享内存的方式完成不同工作进程的数据共享,可以通过 Lua 模块方式完成单个进程内不同请求的数据共享

如何完成单个请求内不同阶段的数据共享呢?ngx.ctx 表就是为了解决这类问题而设计的

location /test {
     rewrite_by_lua_block {
         ngx.ctx.foo = 76
     }
     access_by_lua_block {
         ngx.ctx.foo = ngx.ctx.foo + 3
     }
     content_by_lua_block {
         ngx.say(ngx.ctx.foo)
     }
 }

首先 ngx.ctx 是一个表,所以我们可以对他添加、修改。它用来存储基于请求的 Lua 环境数据,其生存周期与当前请求相同 (类似 Nginx 变量)。它有一个最重要的特性:单个请求内的 rewrite (重写),access (访问),和 content (内容) 等各处理阶段是保持一致的

额外注意,每个请求,包括子请求,都有一份自己的 ngx.ctx 表

 location /sub {
     content_by_lua_block {
         ngx.say("sub pre: ", ngx.ctx.blah)
         ngx.ctx.blah = 32
         ngx.say("sub post: ", ngx.ctx.blah)
     }
 }

 location /main {
     content_by_lua_block {
         ngx.ctx.blah = 73
         ngx.say("main pre: ", ngx.ctx.blah)
         local res = ngx.location.capture("/sub")
         ngx.print(res.body)
         ngx.say("main post: ", ngx.ctx.blah)
     }
 }

访问 GET /main 输出

 main pre: 73
 sub pre: nil
 sub post: 32
 main post: 73
4. 防止SQL注入

对于 MySQL ,可以调用 ndk.set_var.set_quote_sql_str ,进行一次过滤即可,如果恰巧你使用的是 PostgreSQL ,调用 ndk.set_var.set_quote_pgsql_str 过滤输入变量

-- for MySQL
local req_id = [[1'; drop table cats;--]]
res, err, errno, sqlstate =
    db:query(string.format([[select * from cats where id = %s]],
    ndk.set_var.set_quote_sql_str(req_id)))
if not res then
    ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
    return
end
5. 发起新HTTP请求
http {
    server {
        listen    80;

        location /test {
            content_by_lua_block {
                ngx.req.read_body()
                local args, err = ngx.req.get_uri_args()

                local http = require "resty.http"   -- ①
                local httpc = http.new()
                local res, err = httpc:request_uri( -- ②
                    "http://127.0.0.1:81/spe_md5",
                        {
                        method = "POST",
                        body = args.data,
                      }
                )

                if 200 ~= res.status then
                    ngx.exit(res.status)
                end

                if args.key == res.body then
                    ngx.say("valid request")
                else
                    ngx.say("invalid request")
                end
            }
        }
    }

    server {
        listen    81;

        location /spe_md5 {
            content_by_lua_block {
                ngx.req.read_body()
                local data = ngx.req.get_body_data()
                ngx.print(ngx.md5(data .. "*&^%$#$^&kjtrKUYG"))
            }
        }
    }
}

重点解释:
① 引用 resty.http 库资源,它来自 github https://github.com/pintsized/lua-resty-http, 下载tar.gz解压lua文件至openresty/lualib/resty/usr/local/openresty/lualib/resty
② 参考 resty-http 官方 wiki 说明,我们可以知道 request_uri 函数完成了连接池、HTTP 请求等一系列动作

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

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

相关文章

使用Nonebot编写QQ机器人

使用 NoneBot 这个工具,来编写 QQ 机器人。 安装基础软件 一、安装 NoneBot 库 直接使用 pip 安装即可 pip install nonebot二、安装酷Q 软件和 HTTP API 插件 酷Q 软件可以直接到官网下载,https://cqp.cc/b/news,或者可以到网盘下载&am…

TinyLog iOS v3.0接入文档

1.背景 为在线教育部提供高效、安全、易用的日志组件。 2.功能介绍 2.1 日志格式化 目前输出的日志格式如下: 日志级别/[YYYY-MM-DD HH:MM:SS MS] TinyLog-Tag: |线程| 代码文件名:行数|函数名|日志输出内容触发flush到文件的时机: 每15分钟定时触发…

SpringMVC 获取参数

文章目录 1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、[RequestParam ](/RequestParam )4、[RequestHeader ](/RequestHeader )5、[CookieValue ](/CookieValue )6、通过POJO获取请求参数7、解决获取请求参数的乱码问题 1、通过ServletAPI获取 将HttpServlet…

HarmonyOS中的@ohos.promptAction 模块中弹框

在各种APP中会根据不同的业务场景显示不同的弹框情况,针对这些场景API中提示了那些弹框呢?今天就看下: 首先弹框分为模态弹框和非模态弹框,模态弹框必须用户点击反馈后进行下一步操作,非模态弹框只是告知用户信息&…

LeetCode 225.用队列实现栈(详解) ૮꒰ ˶• ༝ •˶꒱ა

题目详情: 思路:1.定义两个队列用于存储栈的数据,其中一个为空。 2.对我们定义的栈进行入数据,就相当于对不为空的队列进行入数据。 3.对我们定义的栈进行删除,相当于取出不为空的队列中的数据放到为空的队列中&#x…

什么是云安全?如何保护云资源

云计算允许组织通过互联网按需向其客户、合作伙伴或员工提供关键业务应用程序、服务和资源。换句话说,不再需要物理维护资源。每当您通过 Internet 从计算机访问文件或服务时,您都是在访问云。 迁移到云可以帮助企业增强安全性、简化运营并降低成本。企…

Linux 常用进阶指令

我是南城余!阿里云开发者平台专家博士证书获得者! 欢迎关注我的博客!一同成长! 一名从事运维开发的worker,记录分享学习。 专注于AI,运维开发,windows Linux 系统领域的分享! 其他…

php 的运算符

目录 1.算数运算符 2.自增自减 3.比较运算符 4.赋值运算 5.逻辑运算符 6.三元运算 1.算数运算符 运算符名称描述a b加和a - b减差a * b乘积a/b除a和b的商a % b模&#xff08;除法的余数&#xff09;a 除以 b的余数-a取负数a 的负数a.b并置连接两个字符串 <?php he…

国内呼叫中心产业的发展趋势和其如何进入国际市场

最近跟一些行内的朋友聊天&#xff0c;能感受到大家的悲观情绪&#xff0c;明年如何&#xff0c;不可知&#xff0c;似乎都没什么信心会更好。 作为OKCC呼叫中心系统厂商&#xff0c;大环境如此&#xff0c;我们也面临同样的问题&#xff0c;同时也从网上和朋友那了解我们这个行…

Enable Kubectl logs/exec to debug pods on the edge

Prepare certs 确保可以找到 Kubernetes 的 ca.crt 和 ca.key 文件。如果您通过 kubeadm 设置您的 Kubernetes 集群&#xff0c;这些文件将位于 /etc/kubernetes/pki/ 目录中。 ls /etc/kubernetes/pki/ 设置 CLOUDCOREIPS 环境变量。该环境变量用于指定 cloudcore 的 IP 地址…

Java泛型:灵活多变的类型参数化工具

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、泛型1、什么是泛型2、泛型的语法 二、泛型类的使用1、泛型类的语法2、泛型如何编译的2.1、擦除机制2.2、为什么不能实例化泛…

coredump+gdb调试

1、什么是coredump Coredump&#xff08;核心转储&#xff09;是操作系统在程序异常终止&#xff08;例如由于段错误或其他严重错误&#xff09;时创建的一种文件。这个文件包含了程序崩溃时刻进程的内存镜像&#xff0c;通常还包括程序计数器、寄存器内容和堆栈内存等信息&am…

Goby高级食用指南

Goby高级食用指南 1.Goby POC2.自定义字典3.Goby插件生态 - 一些好用的插件分享FOFASubDomainsBruteExportCsvAWVSRedis-cliGoby4waf初级篇参考 - Goby基本使用 1.Goby POC Goby的漏洞模块包含官方自定义的一些初始POC: 红队版的POC会实时更新,普通版则不会 Goby的POC编写…

MySQL8.0 升级

将 MySQL8.0.30 升级到 MySQL8.0.32 备份旧数据 rootLAPTOP-FPIQJ438:/data/backup# xtrabackup --backup --userroot --password123456 --socket/tmp/mysql.sock --target-dir/data/backup/ 2024-01-08T16:46:38.98768708:00 0 [Note] [MY-011825] [Xtrabackup] recognized s…

江山易改本性难移之ZYNQ SDK QSPI固化bug及其解决方法

之前在Vivado2018.3通过QSPI方式固化程序时出现问题&#xff0c;显示flash擦除成功&#xff0c;但最后总是不能写入到flash中。 查资料发现从VIVADO 2017.3版本开始&#xff0c;Xilinx官方为了使Zynq-7000和Zynq UltraScale 实现流程相同&#xff0c;在QSPI FLASH使用上做了变化…

VSCode C/C++(gdb)调试指南

1、安装插件 2、F5开启调试 左侧侧边栏->确保打开回调栈 右键函数栈->查看反汇编 3、打印寄存器、函数反汇编等 命令&#xff1a; 查看main反汇编 -exec disassemble /m main 查看寄存器 -exec info r 打印某个变量 -exec print s 或者 --s 打印寄存器&#xff0c;如p…

Git删除远程仓库某次提交记录后的所有提交

1、鼠标右键->git bash here&#xff0c;然后cd切换到代码目录&#xff1b; 2、git log查看提交记录&#xff0c;获取commit id 3、git reset commit id&#xff08;commit id指要保留的最新的提交记录id&#xff09; 4、git push --force&#xff0c;强制push 如果出现…

来自一个系统的自白

天空一声巨响&#xff0c;小炫我闪亮登场&#xff01;初次见面&#xff0c;给大家简单介绍下自己&#xff1a;我是炫我渲染私有云系统&#xff0c;是最新一代的智能渲染集群系统。可以进行私有化部署&#xff0c;在3dsmax、maya等软件中一键完成提交、上传、渲染、下载的任务&a…

强化学习第1天:马尔可夫过程

☁️主页 Nowl &#x1f525;专栏 《强化学习》 &#x1f4d1;君子坐而论道&#xff0c;少年起而行之 ​​ 一、介绍 什么是马尔可夫过程&#xff1f;马尔可夫过程是马尔可夫决策过程的基础&#xff0c;而马尔可夫决策过程便是大部分强化学习任务的抽象过程&#xff0c;本文…

人机交互不是人机融合智能

一、人机交互和人机融合智能是两个不同的概念 人机交互是指人类与计算机之间的信息交流和操作方式&#xff0c;包括输入和输出界面、交互技术、用户体验等方面。人机交互的目标是提供用户友好的界面和自然的交互方式&#xff0c;使人类能够与计算机更加高效地进行沟通和协作。 …