[Bug] Website statistics queue cursor is not initialized, causing worker 0 to periodically scan historical sequence numbers and block requests
Los mantenedores suelen responder en 1 día
@wanghe-fit2cloud ya está trabajando en esto.
Desde el 11/10/2026.
Evaluación
Este issue todavía no se ha evaluado.
Descripción
Contact Information
No response
1Panel Version
v1.10.34-lts stable
Problem Description
- OpenResty 镜像:
1panel/openresty:1.21.4.3-3-3-focal - 内置 1Panel WAF:1.0.0
- 网站访问统计:开启
- 请求链路:浏览器 → OpenResty → Nginx gateway → Node.js WMS
网站累计大量请求后,OpenResty 单个 worker 持续占用约 70–80% CPU,部分 HTTP 请求首字节等待超过 6 秒,而后端实际处理仅需毫秒。服务器本机重放也曾测到 13.44 秒首字节等待。
检查当前镜像的 Lua 字节码及运行时状态发现:
- worker 0 每 3 秒调用
monitor_task.insert_log。 - 任务从
ngx.shared.waf读取<site>_sql_start,缺失时以局部值 1 作为循环起点。 - 循环中直接调用
incr(key, 1),没有先初始化共享字典中的键,也没有处理递增失败。 - 对不存在的键执行 incr 不会创建键,因此共享游标始终为 nil,每轮重新遍历
1..累计序号。 - 已消费并删除的队列记录仍被反复查找,同步循环阻塞处理 HTTP 请求的 worker。
现场某站点累计序号为 1,555,625,游标仍为 nil。无新增请求时,任务仍反复耗时约 2.6–2.8 秒;探针另观察到 5.06 秒、8.61 秒的调用耗时,其中可能包含锁等待。
Steps to Reproduce
- 使用上述镜像,开启网站访问统计。
- 持续正常访问站点,使统计队列累计序号增长,无需维持高并发。
- 检查 worker 0 CPU 和 HTTP 首字节等待时间。
- 在统计任务中读取共享字典,比较
<site>_sql与<site>_sql_start。本现场累计序号超过 155 万,而游标为 nil。 - 停止新增流量,观察统计任务仍每 3 秒反复执行约 2.6–2.8 秒。
- 首次消费前初始化缺失游标,再对比 CPU 和请求延迟。
The expected correct result
首次消费前应安全初始化游标,检查共享字典操作结果。后续只处理未消费记录,不能随累计历史序号反复扫描。
建议回归覆盖:游标缺失恢复、已有游标保留、新记录继续消费、共享内存不足处理,以及 reload/共享内存重建。进一步建议限制每轮消费数量或执行时间,避免统计任务长时间占用请求 worker。
Related log output
以下为脱敏摘录,任务耗时由临时包装器在调用前后更新 ngx 时间后测量:
site_sql=1555625
site_sql_start=nil
worker=0 task=monitor_task.insert_log elapsed_ms=2745
worker=0 task=monitor_task.insert_log elapsed_ms=8614
worker=0 task=monitor_task.insert_log elapsed_ms=2789
某次本机重放的 OpenResty 日志:
request_time=6.943s
upstream_connect_time=4.282s
upstream_header_time=6.943s
Server-Timing: auth;dur=0.5, total;dur=0.6
Nginx 阶段时间由 worker 观察,worker 停顿会延迟事件处理,不能直接认定本机 TCP 建连实际花了 4.282 秒。
Additional Information
现场兼容补丁在原统计任务前初始化缺失游标,再执行厂商原有 worker.lua,保留其任务、锁和定时器:
if ngx.worker.id() == 0 then
local config = require("config")
local monitor = require("monitor_task")
local insert_log = monitor.insert_log
monitor.insert_log = function(...)
for _, site in ipairs(config.get_website_keys() or {}) do
local key = site .. "_sql_start"
if ngx.shared.waf:get(key) == nil then
local ok, err = ngx.shared.waf:safe_add(key, 1)
if not ok and err ~= "exists" then
ngx.log(ngx.ERR, "WAF monitor cursor initialization failed: ", err)
return
end
end
end
return insert_log(...)
end
end
dofile("/usr/local/openresty/1pwaf/worker.lua")
从 1 恢复以保留仍待消费的队列项,首次仍需追赶历史序号,此后游标正常前进。未清空队列或数据库,未停用 WAF。
修复后:
- OpenResty CPU 一次采样降至 0.14%,后续另一次采样为 3.21%。
- 初始化恢复完成后,未再观察到超过探针阈值 250 ms 的统计任务;新增访问仍正常写入数据库。
- 服务器分层验证 320 次有效 WMS 请求全部返回 200。
- Windows 全新 Edge 上下文通过 HTTP/2 实际加载、拖动、缩放地图,637 次 WMS 请求全部返回 200,无失败或取消,无浏览器磁盘缓存命中。
- 浏览器等待响应 P95 423.44 ms,最大 901.29 ms,无超过 1 秒的样本;样本包含 WMS 能力查询。
- 最慢首次请求后端 auth=471.8 ms、asset=399.6 ms、total=872.1 ms,与浏览器等待基本吻合。
这是短时回归,不代表所有网络或负载的延迟上限
类似现象:#13583,涉及 worker 0 的日志任务高 CPU,但其根因是 SQLite event_id 索引,本次则为共享字典游标缺失。
- Lenguaje dominante
- Go
- Estrellas
- 37.1k
- Forks
- 3.4k
- Merge medio
- 13 h
- PR fusionados (30 d)
- 82
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de 1Panel-dev/1Panel
-
[Bug] AI Gateway Concurrency ErrorsPosiblemente ocupada @wanghe-fit2cloud la tomó hoy. Abiertotype: ai-gateway
1Panel-dev/1Panel#14035 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
[Bug] Excessive Overhead in the Embedding GatewayPosiblemente ocupada @wanghe-fit2cloud la tomó hoy. Abiertotype: ai-gateway
1Panel-dev/1Panel#14034 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
[Feature] Human VerificationPosiblemente ocupada @wanghe-fit2cloud la tomó hace 1 día. Abiertotype: feature-request
1Panel-dev/1Panel#14027 · 3 comentarios · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
[Bug] All models added by the Qwen Token Plan are recognized as text models.Posiblemente ocupada @wanghe-fit2cloud la tomó hace 1 día. Abiertotype: ai-gateway
1Panel-dev/1Panel#14026 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
[Bug] iptables Rule Persistence and Restoration Order IssuesPosiblemente ocupada @wanghe-fit2cloud la tomó hace 2 días. Abiertostatus: dev-complete type: optimization
1Panel-dev/1Panel#14019 · 2 comentarios · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de 1Panel-dev/1Panel
Issues similares
-
[schema-coverage] elasticstack_kibana_security_detection_rulePosiblemente ocupada @github-actions la tomó hoy. Abiertoacceptance-tests phase-coding schema-coverage testing triaged
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
elastic/terraform-provider-elasticstack#5186 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
jaegertracing/jaeger#9830 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
apache/rocketmq-dashboard#6318 ·
Los mantenedores suelen responder en 5 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 83/100
GoogleCloudPlatform/opentelemetry-operations-collector#710 ·
Los mantenedores suelen responder en 1 día