2020-03-05 19:50:16
有些时候,我们需要通过 Lua 代码操作 Nginx 里面的某些状态,但是想要的 API 并不存在于 OpenResty 之内。这时候,可以选择编写一个 Nginx C 模块,然后暴露出可供 Lua 调用的接口。
本文中,我们会分别探讨,如何通过 Nginx 变量或 FFI 的方式去提供 Lua 调用得到的接口。
文中的示例代码可以在 ngx_http_example_or_module 找到。
ngx.var.variable= 在调用的时候,会先查找变量 variable 对应的 handler(一个在 Nginx 内注册的 C 函数),如果 handler 存在,会去调用该 handler。
这意味着,如果我们定义了一个 Nginx 变量和对应的 handler,我们就可以通过在 Lua 代码里调用 ngx.var.variable= 来触发该 handler。
空说无益,先上示例。
在 Nginx 里面我们可以通过 limit_rate 和 limit_rate_after 两个指令来限制响应给客户端的速率。前者决定了限速的多少,后者决定了从什么时候开始限速。当然更多的时候我们需要动态去调整这两个指标。
limit_rate 对应有一个 Nginx 内置的变量, $limit_rate,我们可以修改该变量来达到动态调整的目的。相关的 Lua 代码是 ngx.var.limit_rate = limit_rate。但是并不存在 $limit_rate_after 这样一个变量。
不用担心。因为我们可以自己加上。
// ngx_http_example_or_module.c
// 定义变量和它的 getter/setter
static ngx_http_variable_t ngx_http_example_or_variables[] = {
{ ngx_string("limit_rate_after"), ngx_http_variable_request_set_size,
ngx_http_variable_request_get_limit_rate_after,
offsetof(ngx_http_request_t, limit_rate_after),
NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
};
// getter 和 setter 的实现在 GitHub 上的示例代码里有,这里就不贴上了。
不过在大多数情况下,我们并不需要借助变量来间接调用 Nginx C 函数。我们完全可以借助 LuaJIT 的 FFI,直接调用 Nginx C 函数。
lua-resty-murmurhash2 就是一个现成的例子。
下面让我们再看另外一个例子,通过 Lua 代码来获取当前的 Nginx 错误日志等级。
在开发中,我们有时需要在测试环境中通过日志来记录某个 table 的值,比如 ngx.log(ngx.INFO, cjson.encode(res))。
在生产环境里,我们会设置日志等级为 error,这样就不会输出 table 的值。但是日志等级无论是多少,cjson.encode 都是必然会被调用的。
不幸的是,这行代码所在的路径非常热,我们需要避免无谓的 json encode 操作。如果能获取实际的日志等级,判断是否为 error,来决定是否调用 cjson.encode,就能省下这一笔开销。
要实现这一功能,仅需加个获取当前配置的日志等级的 Nginx C 函数和对应的 Lua 接口。
我们可以像这样提供一个 Lua 接口:
-- lib/example_or.lua
...
if not pcall(ffi.typeof, "ngx_http_request_t") then
ffi.cdef[[
struct ngx_http_request_s;
typedef struct ngx_http_request_s ngx_http_request_t;
]]
end
ffi.cdef[[
int ngx_http_example_or_ffi_get_error_log_level(ngx_http_request_t *r);
]]
function _M.get_error_log_level()
local r = getfenv(0).__ngx_req
return tonumber(C.ngx_http_example_or_ffi_get_error_log_level(r))
end
对应的 Nginx C 函数很简单:
int
ngx_http_example_or_ffi_get_error_log_level(ngx_http_request_t *r)
{
ngx_log_t *log;
int log_level;
if (r && r->connection && r->connection->log) {
log = r->connection->log;
} else {
log = ngx_cycle->log;
}
log_level = log->log_level;
if (log_level == NGX_LOG_DEBUG_ALL) {
log_level = NGX_LOG_DEBUG;
}
return log_level;
}
使用时直接拿它跟特定的 Nginx 日志等级常量比较即可:
-- config.lua
-- 目前 Nginx 不支持动态变更日志等级,所以可以把日志等级缓存起来
local example_or = require "lib.example_or"
_M.log_leve = example_or.get_error_log_level()
-- in other file
local config = require "common.config"
local log_level = config.log_level
if log_level >= ngx.WARN then
-- 错误日志等级是 warn 或者 info 一类
ngx.log(ngx.WARN, "log a warning event")
else
-- 错误日志等级是 error 一类
ngx.log(ngx.WARN, "do not log another warning event")
end
OpenResty(Nginx Lua)统计网站访问信息
07-07
saltstaCk自定义模块
05-02
OpenResty json 删除转义符
07-16
OpenResty设置用于aCCess_log的自定义变量
02-18
ThinkCentre 自定义恢复出厂设置
03-16
Nginx ngx_http_limit_Conn ngx_http_limit_Conn模块(请求限制和连接数限制)使用指南
03-20
JVM类加载器是否可以加载自定义的String
06-18
Kubernetes之配置与自定义DNS服务
05-24
微软 Powertoys 推出新的实用程序,自定义键盘快捷管理
05-06
CentOS7源码编译安装Nginx
06-11
如何在CentOS 7上安装Nginx
07-05
Nginx HTTP2配置教程
06-23
Nginx配置basiC_auth密码验证
06-13
Ubuntu 16.04配置Nginx使用GeoIP
07-12
【工作】Nginx 实现域名的登录验证功能
07-04
DoCker Compose 项目打包部署
04-17
Nginx编译安装动态模块(不需重新编译Nginx)
06-25
Linux ApaChe安装加载mod_deflate模块
04-11
Linux insmod载入模块命令详解
07-04
Linux lsmod显示已载入系统的模块命令详解
07-24
MagiCMouseTrails(自定义鼠标拖尾工具) v1.31 绿色中文版
388K
下载Teambition(项目协作工具) v1.13.0.0 免费版
44.6M
下载子美建筑工地管理系统(工地施工项目管理系统) v2021.07.01 官方版
57.8M
下载考无忧2017职称计算机模块-用友T3财务软件 v17.1
38.95 MB
下载考无忧2018职称计算机模块-ExCel2003模块 v18.2
62.3 MB
下载考无忧2018职称计算机模块-ExCel2007模块 v18.2
63.05 MB
下载考无忧2018职称计算机模块-FrontPage2000 v18.1
57.47 MB
下载考无忧2018职称计算机模块-Word 2007模块 v18.2
73.9 MB
下载7CMenuEditor官方下载 V4.5.0.0官方版
188KB
下载职称考试计算机AutoCAD2004
51.66 MB
下载职称考试计算机PhotoShop CS
64.3 MB
下载Cool edit pro 2.1
16.2M
下载Sublime Text 3下载
52MB
下载UltraSnap Pro抓图软件
13.68 MB
下载aCmeCadConverter下载
8.92MB
下载aCtivesynC(电脑数据同步工具) v6.1 免费版
22.72MB
下载dreamweaver Cs5(网页设计制作软件)2021 免费版
405.98 MB
下载easyreCovery pro(硬盘数据恢复工具) v14.0.0.4 官方版
87.8M
下载fastCopy下载
1.5M
下载flash Cs4下载
164.2M
下载