Nginx结合Lua模块(OpenResty)可以高效地实现网站数据收集功能。下面我将介绍完整的实现方案。
# 推荐直接安装OpenResty
wget https://openresty.org/package/centos/openresty.repo
sudo mv openresty.repo /etc/yum.repos.d/
sudo yum install -y openresty
在nginx.conf中添加Lua支持:
http {
lua_package_path "/path/to/lua/scripts/?.lua;;";
lua_shared_dict stats 10m; # 共享内存区域用于临时存储
init_by_lua_block {
-- 初始化全局变量和连接池
local redis = require "resty.redis"
local red = redis:new()
-- 可以在这里初始化数据库连接等
}
}
server {
location / {
access_by_lua_block {
-- 获取基础信息
local ngx_var = ngx.var
local request_uri = ngx_var.request_uri
local http_referer = ngx_var.http_referer or "direct"
local http_user_agent = ngx_var.http_user_agent or "unknown"
local remote_addr = ngx_var.remote_addr
-- 获取cookie中的用户ID
local cookies = ngx_var.http_cookie
local user_id = "anonymous"
if cookies then
user_id = string.match(cookies, "user_id=([^;]+)") or user_id
end
-- 构造数据对象
local log_data = {
time = ngx.now(),
uri = request_uri,
referer = http_referer,
ua = http_user_agent,
ip = remote_addr,
user_id = user_id,
status = ngx.status
}
-- 发送到后端存储
local cjson = require "cjson"
local redis = require "resty.redis"
local red = redis:new()
local ok, err = red:connect("127.0.0.1", 6379)
if ok then
red:rpush("web_stats", cjson.encode(log_data))
red:set_keepalive(10000, 100)
end
}
}
}
对于更复杂的行为跟踪(如页面停留时间、点击事件等),可以使用JavaScript+API的方式:
location /api/track {
content_by_lua_block {
local args = ngx.req.get_uri_args()
local event_type = args.event or "pageview"
local duration = args.duration or 0
local element = args.element or ""
-- 验证数据并处理
if not ngx.var.http_referer then
ngx.exit(403)
end
-- 构造事件数据
local event_data = {
time = ngx.now(),
event = event_type,
duration = tonumber(duration),
element = element,
referer = ngx.var.http_referer,
user_agent = ngx.var.http_user_agent,
ip = ngx.var.remote_addr
}
-- 发送到Kafka或其他消息队列
local kafka = require "resty.kafka"
local producer = kafka:new("kafka_cluster", {
broker_list = {
{ host = "kafka1", port = 9092 },
{ host = "kafka2", port = 9092 }
}
})
local ok, err = producer:send("web_events", nil, cjson.encode(event_data))
if not ok then
ngx.log(ngx.ERR, "failed to send event to kafka: ", err)
end
ngx.say("ok")
}
}
可以使用Lua的共享内存进行简单的实时统计:
init_by_lua_block {
-- 初始化计数器
local stats = ngx.shared.stats
stats:set("pageviews", 0)
stats:set("visitors", 0)
-- 其他需要统计的指标...
}
access_by_lua_block {
-- 在访问时更新统计
local stats = ngx.shared.stats
stats:incr("pageviews", 1)
-- 基于IP的独立访客统计
local ip = ngx.var.remote_addr
local key = "visitor:" .. ip
local seen = stats:get(key)
if not seen then
stats:set(key, 1, 3600) -- 1小时过期
stats:incr("visitors", 1)
end
}
性能优化:
数据可靠性:
隐私合规:
扩展性:
/etc/nginx/
├── nginx.conf
└── lua/
├── init.lua # 初始化脚本
├── stats/ # 统计模块
│ ├── core.lua # 核心功能
│ ├── storage.lua # 存储适配器
│ └── utils.lua # 工具函数
└── config.lua # 配置文件
通过这种架构,你可以灵活地扩展数据收集功能,同时保持Nginx的高性能特性。