feat(syslog): 增加积压采样免采样窗口
- 新增 start-lag-ms 配置,默认15分钟内全量保留 - 在15分钟至1小时之间按10级逐步降低保留率 - 延迟达到1小时后使用普通10%、非标20%的最低保留率 - 校验起始延迟必须小于最低保留率阈值 - 状态接口新增 start_lag_ms 配置展示 - 将采样策略版本升级为 v2 - 更新 Docker Compose 和 v4 升级配置说明 - 补充采样时间边界及非法配置单元测试
This commit is contained in:
@@ -7,11 +7,13 @@
|
||||
| `v1/` | 原有升级资料 |
|
||||
| `v2/` | 从提交 `b61ec2e` 升级到当前源码所需的增量资料 |
|
||||
| `v3/` | 日统计异步投影,以及大日志独立 Kafka 通道、字节背压和存储截断升级资料 |
|
||||
| `v4/` | Kafka 积压分级采样、告警优先落库和 InfluxDB 非阻塞旁路升级资料 |
|
||||
|
||||
新环境按 v1、v2、v3 的顺序执行;已经完成 v2 的现场只执行 v3。已经执行过早期 v3 日统计升级的
|
||||
现场,只需补做 v3 中的大日志 Topic、应用升级和验证步骤,不要重复执行数据库升级脚本。
|
||||
新环境按 v1、v2、v3、v4 的顺序执行;已经完成 v3 的现场只执行 v4。已经执行过早期 v3 日统计升级的
|
||||
现场,只需补做 v3 中的大日志 Topic、应用升级和验证步骤,再执行 v4;不要重复执行数据库升级脚本。
|
||||
|
||||
数据库脚本不要重复执行。执行过程中有报错时,先确认已经落库的对象,再决定从哪里继续。
|
||||
|
||||
v2 的执行步骤见 [v2/README.md](./v2/README.md)。
|
||||
v3 的执行步骤见 [v3/README.md](./v3/README.md)。
|
||||
v4 的执行步骤见 [v4/README.md](./v4/README.md)。
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# 物理清空指定 Kafka Topic 中当前已有的消息,但保留 Topic 本身、分区、副本和配置。
|
||||
#
|
||||
# 默认值对应当前客户现场,复制到 Kafka 主机后可直接执行:
|
||||
# bash 04-clear-topic-messages.sh
|
||||
#
|
||||
# 清理其他 Topic 时可覆盖 TARGET_TOPIC:
|
||||
# TARGET_TOPIC=other-topic bash 04-clear-topic-messages.sh
|
||||
#
|
||||
# 有认证的集群需额外设置:
|
||||
# COMMAND_CONFIG=/path/to/client.properties bash 04-clear-topic-messages.sh
|
||||
#
|
||||
# 注意:
|
||||
# - 执行前必须停止目标 Topic 的生产者和消费者;
|
||||
# - 消息删除后通常不可恢复;
|
||||
# - 本脚本不会删除 Topic,也不会修改任何消费组 offset;
|
||||
# - 若消费组 offset 低于删除后的日志起始 offset,消费者后续行为取决于 auto.offset.reset。
|
||||
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||
BOOTSTRAP="${BOOTSTRAP:-10.141.121.35:9092,10.141.121.50:9092,10.141.121.59:9092}"
|
||||
RAW_TOPIC="${RAW_TOPIC:-agent-01-syslog-topic}"
|
||||
TARGET_TOPIC="${TARGET_TOPIC:-${RAW_TOPIC}}"
|
||||
|
||||
if [[ ! "${TARGET_TOPIC}" =~ ^[a-zA-Z0-9._-]+$ ]]; then
|
||||
echo "ERROR: TARGET_TOPIC 包含非法字符:${TARGET_TOPIC}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 优先使用调用方显式指定的目录;否则自动识别脚本同目录、现场 Kafka 安装目录或 PATH。
|
||||
if [[ -z "${KAFKA_BIN:-}" ]]; then
|
||||
for CANDIDATE_BIN in \
|
||||
"${SCRIPT_DIR}" \
|
||||
"/opt/kafka/kafka_2.13-3.6.1/bin" \
|
||||
"/opt/kafka/bin"; do
|
||||
if [[ -x "${CANDIDATE_BIN}/kafka-topics.sh" ]] \
|
||||
&& [[ -x "${CANDIDATE_BIN}/kafka-delete-records.sh" ]]; then
|
||||
KAFKA_BIN="${CANDIDATE_BIN}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ -z "${KAFKA_BIN:-}" ]] \
|
||||
&& command -v kafka-topics.sh >/dev/null 2>&1 \
|
||||
&& command -v kafka-delete-records.sh >/dev/null 2>&1; then
|
||||
KAFKA_BIN=$(dirname -- "$(command -v kafka-topics.sh)")
|
||||
fi
|
||||
|
||||
if [[ -z "${KAFKA_BIN:-}" ]]; then
|
||||
echo "ERROR: 未找到 Kafka CLI;现场预期路径为 /opt/kafka/kafka_2.13-3.6.1/bin" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TOPICS_CMD="${KAFKA_BIN}/kafka-topics.sh"
|
||||
DELETE_RECORDS_CMD="${KAFKA_BIN}/kafka-delete-records.sh"
|
||||
|
||||
if [[ ! -x "${TOPICS_CMD}" ]] || [[ ! -x "${DELETE_RECORDS_CMD}" ]]; then
|
||||
echo "ERROR: ${KAFKA_BIN} 下缺少 kafka-topics.sh 或 kafka-delete-records.sh" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
COMMON_ARGS=(--bootstrap-server "${BOOTSTRAP}")
|
||||
if [[ -n "${COMMAND_CONFIG:-}" ]]; then
|
||||
if [[ ! -r "${COMMAND_CONFIG}" ]]; then
|
||||
echo "ERROR: 无法读取认证配置 ${COMMAND_CONFIG}" >&2
|
||||
exit 1
|
||||
fi
|
||||
COMMON_ARGS+=(--command-config "${COMMAND_CONFIG}")
|
||||
fi
|
||||
|
||||
RUN_ID=$(date '+%Y%m%d_%H%M%S')
|
||||
AUDIT_DIR="${CLEAR_AUDIT_DIR:-./kafka-message-clear-${RUN_ID}}"
|
||||
mkdir -p "${AUDIT_DIR}"
|
||||
|
||||
BEFORE_FILE="${AUDIT_DIR}/topic-before.txt"
|
||||
DELETE_JSON="${AUDIT_DIR}/delete-records.json"
|
||||
DELETE_RESULT="${AUDIT_DIR}/delete-result.txt"
|
||||
AFTER_FILE="${AUDIT_DIR}/topic-after.txt"
|
||||
|
||||
echo "目标 Kafka:${BOOTSTRAP}"
|
||||
echo "目标 Topic:${TARGET_TOPIC}"
|
||||
echo "Kafka CLI:${KAFKA_BIN}"
|
||||
echo "审计目录:${AUDIT_DIR}"
|
||||
|
||||
echo "[1/5] 测试 Kafka 连接并确认 Topic 存在"
|
||||
"${TOPICS_CMD}" "${COMMON_ARGS[@]}" --list >/dev/null
|
||||
TOPIC_INFO=$("${TOPICS_CMD}" "${COMMON_ARGS[@]}" --describe --topic "${TARGET_TOPIC}")
|
||||
printf '%s\n' "${TOPIC_INFO}" | tee "${BEFORE_FILE}"
|
||||
|
||||
PARTITION_COUNT=$(printf '%s\n' "${TOPIC_INFO}" | awk '
|
||||
/PartitionCount:/ {
|
||||
for (i=1; i<=NF; i++) if ($i=="PartitionCount:") { print $(i+1); exit }
|
||||
}
|
||||
')
|
||||
|
||||
if [[ ! "${PARTITION_COUNT}" =~ ^[1-9][0-9]*$ ]]; then
|
||||
echo "ERROR: 无法确认 ${TARGET_TOPIC} 的分区数,拒绝继续" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[2/5] 为 ${PARTITION_COUNT} 个分区生成删除清单"
|
||||
printf '%s\n' "${TOPIC_INFO}" | awk -v topic="${TARGET_TOPIC}" '
|
||||
BEGIN {
|
||||
printf "{\"partitions\":["
|
||||
first=1
|
||||
}
|
||||
/Partition:/ {
|
||||
for (i=1; i<=NF; i++) {
|
||||
if ($i=="Partition:" && $(i+1)~/^[0-9]+$/) {
|
||||
if (!first) printf ","
|
||||
printf "{\"topic\":\"%s\",\"partition\":%s,\"offset\":-1}", topic, $(i+1)
|
||||
first=0
|
||||
}
|
||||
}
|
||||
}
|
||||
END {
|
||||
print "],\"version\":1}"
|
||||
}
|
||||
' > "${DELETE_JSON}"
|
||||
|
||||
DELETE_ROWS=$(awk -F'"partition":' '{count+=NF-1} END {print count+0}' "${DELETE_JSON}")
|
||||
if [[ "${DELETE_ROWS}" -ne "${PARTITION_COUNT}" ]]; then
|
||||
echo "ERROR: 删除清单只识别到 ${DELETE_ROWS}/${PARTITION_COUNT} 个分区,拒绝继续" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat "${DELETE_JSON}"
|
||||
|
||||
EXPECTED_CONFIRM="CLEAR:${TARGET_TOPIC}:${PARTITION_COUNT}"
|
||||
echo "[3/5] 等待人工确认"
|
||||
echo "警告:将永久删除 ${TARGET_TOPIC} 当前已有的全部消息,但保留 Topic。"
|
||||
echo "请确认生产者和消费者均已停止。"
|
||||
echo "如确认执行,请完整输入:${EXPECTED_CONFIRM}"
|
||||
|
||||
if [[ -n "${CONFIRM_CLEAR:-}" ]]; then
|
||||
CONFIRM_INPUT="${CONFIRM_CLEAR}"
|
||||
elif [[ -t 0 ]]; then
|
||||
read -r CONFIRM_INPUT
|
||||
else
|
||||
echo "ERROR: 当前不是交互终端;必须通过 CONFIRM_CLEAR 提供精确确认串" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${CONFIRM_INPUT}" != "${EXPECTED_CONFIRM}" ]]; then
|
||||
echo "CANCELLED: 确认串不匹配,未删除任何消息。" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[4/5] 清空 Topic 当前已有消息"
|
||||
"${DELETE_RECORDS_CMD}" "${COMMON_ARGS[@]}" \
|
||||
--offset-json-file "${DELETE_JSON}" | tee "${DELETE_RESULT}"
|
||||
|
||||
echo "[5/5] 再次检查 Topic"
|
||||
"${TOPICS_CMD}" "${COMMON_ARGS[@]}" \
|
||||
--describe --topic "${TARGET_TOPIC}" | tee "${AFTER_FILE}"
|
||||
|
||||
echo "PASS: ${TARGET_TOPIC} 当前已有消息已提交物理删除。"
|
||||
echo "Topic、分区、副本和配置均保留,消费组 offset 未修改。"
|
||||
echo "执行记录:${AUDIT_DIR}"
|
||||
@@ -10,7 +10,7 @@ v3 将以下统计表的热点更新移出 `syslog-consumer-rule` 事实事务
|
||||
|
||||
事实事务只批量写事实表并追加一条聚合 Outbox。独立的 Kafka 投影消费者串行更新日统计,之后继续通过
|
||||
已有的 `STATS.MATERIALIZE` Topic 刷新 `device_device`、`dm_normalize_rule` 和
|
||||
`device_collect_task`。这样三台 `syslog-consumer-rule` 可以并行写事实,不再同时争抢相同日统计行锁。
|
||||
`device_collect_task`。单节点和多节点部署都不再让事实写入争抢日统计行锁。
|
||||
|
||||
v3 同时增加大日志独立处理链路:
|
||||
|
||||
@@ -36,8 +36,8 @@ v3 同时增加大日志独立处理链路:
|
||||
|
||||
数据库脚本必须使用 `syslog-consumer-rule` 实际连接的达梦用户执行。
|
||||
|
||||
如果现场已经执行过早期 v3 日统计异步投影升级,只执行 `kafka/02-create-large-log-topics.sh` 和本页的
|
||||
大日志应用配置、验证步骤;不要重复执行数据库升级脚本。
|
||||
如果现场已经执行过早期 v3 日统计异步投影升级,只执行大日志 Kafka 脚本和应用配置,不要重复执行
|
||||
数据库升级脚本。
|
||||
|
||||
## 第一步:达梦
|
||||
|
||||
@@ -117,10 +117,10 @@ PASS: 大日志 Topic 已创建并统一配置。
|
||||
|
||||
## 第三步:升级应用
|
||||
|
||||
升级 `syslog-serve` 和三台 `syslog-consumer-rule`;`syslog-consumer` 不需要因为本次改造升级。
|
||||
升级 `syslog-serve` 和现场的 `syslog-consumer-rule`;`syslog-consumer` 不需要因为本次改造升级。
|
||||
|
||||
升级前先按 [新增变量配置清单](./config/01-new-environment-variables.md) 修改现场实际使用的 Compose 文件。
|
||||
三台 `syslog-consumer-rule` 的 Topic、消费组和截断上限必须保持一致。
|
||||
如果部署了多个 `syslog-consumer-rule`,它们的 Topic、消费组和截断上限必须保持一致。
|
||||
|
||||
统计投影默认已经启用。确认现场没有显式配置:
|
||||
|
||||
@@ -128,9 +128,7 @@ PASS: 大日志 Topic 已创建并统一配置。
|
||||
STATS_PROJECTION_ASYNC_ENABLED=false
|
||||
```
|
||||
|
||||
先逐台升级 `syslog-consumer-rule`,可以启动一台观察后再升级另外两台;确认大日志 listener 正常后再
|
||||
升级 `syslog-serve`。新旧版本滚动期间,同一条原始 Kafka 消息只会被消费组中的一个实例处理,不会因为
|
||||
滚动升级重复统计。
|
||||
先升级 `syslog-consumer-rule`;多实例时逐台滚动。确认大日志 listener 正常后再升级 `syslog-serve`。
|
||||
|
||||
## 升级后验证
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ syslog-serve/docker-compose/docker-compose-serve-prod.yaml
|
||||
syslog-consumer-rule/docker-compose/docker-compose-consumer-rule-prod.yaml
|
||||
```
|
||||
|
||||
在 `services.syslog-consumer-rule.environment` 中增加,三台实例保持一致:
|
||||
在 `services.syslog-consumer-rule.environment` 中增加;如果以后部署多实例,各实例保持一致:
|
||||
|
||||
```yaml
|
||||
# 大日志独立消费通道。
|
||||
@@ -160,4 +160,4 @@ docker compose -f docker-compose-consumer-rule-prod.yaml config
|
||||
docker compose -f docker-compose-consumer-rule-prod.yaml up -d --force-recreate syslog-consumer-rule
|
||||
```
|
||||
|
||||
建议先升级三台 `syslog-consumer-rule`,确认大日志消费者正常后,再升级 `syslog-serve`。
|
||||
建议先升级 `syslog-consumer-rule`,确认大日志消费者正常后,再升级 `syslog-serve`。
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
# v4 积压分级采样与告警优先升级说明
|
||||
|
||||
## 升级范围
|
||||
|
||||
v4 只升级 `syslog-consumer-rule` 和达梦数据库,不修改 `syslog-serve`,也不新增 Kafka Topic。
|
||||
|
||||
本次升级包含:
|
||||
|
||||
- 根据消息 `receive_time` 与当前时间的差值,对积压消息分级采样;
|
||||
- `syslog_normal_alarm` 始终全量保留,并在 InfluxDB 原文、普通表和非标表之前单独提交;
|
||||
- 未被保留的 `syslog_normal_data`、`syslog_non_normal_message` 及对应原文不写入存储;
|
||||
- 按消息来源小时、Topic、Partition、策略版本和实际保留率记录采样审计;
|
||||
- 审计表不可用时自动回退为全量保留,不执行有损采样;
|
||||
- InfluxDB 原文写入变为非关键旁路,启动检查或运行时写入失败只记录并继续主消费。
|
||||
|
||||
## 文件与执行顺序
|
||||
|
||||
| 顺序 | 文件 | 作用 |
|
||||
| --- | --- | --- |
|
||||
| 1 | `database/01-backlog-sampling-precheck.sql` | 只读检查目标表、约束和索引是否已经存在 |
|
||||
| 2 | `database/02-backlog-sampling-upgrade.sql` | 创建积压采样小时审计表,仅执行一次 |
|
||||
| 3 | `database/03-backlog-sampling-verify.sql` | 只读验证表结构,并查看实际保留情况 |
|
||||
| 4 | `config/01-new-environment-variables.md` | 核对新增配置,再替换 `syslog-consumer-rule` JAR |
|
||||
|
||||
数据库脚本必须使用 `syslog-consumer-rule` 实际连接的达梦用户执行。
|
||||
|
||||
## 第一步:升级达梦
|
||||
|
||||
先执行:
|
||||
|
||||
```text
|
||||
database/01-backlog-sampling-precheck.sql
|
||||
```
|
||||
|
||||
- 如果目标表、约束和索引都不存在,执行 `02-backlog-sampling-upgrade.sql`,再执行
|
||||
`03-backlog-sampling-verify.sql`;
|
||||
- 如果目标表已经存在,不要重复执行 `02`,直接执行 `03` 核对结构;
|
||||
- 如果只存在部分对象,先停止升级并确认此前执行到哪一步,不要盲目重跑建表脚本。
|
||||
|
||||
`03` 验证应满足:
|
||||
|
||||
- 返回 `SYSLOG_BACKLOG_RETENTION_HOURLY` 一张表;
|
||||
- 表包含 22 个字段;
|
||||
- 主键和保留率检查约束状态为 `ENABLED`;
|
||||
- 更新时间索引状态为 `VALID`。
|
||||
|
||||
## 第二步:配置并升级应用
|
||||
|
||||
按 [新增变量配置清单](./config/01-new-environment-variables.md) 核对配置,然后替换并重启
|
||||
`syslog-consumer-rule`。只替换 JAR、不增加环境变量时,积压采样也会按 JAR 内置默认值开启,因此必须先
|
||||
完成数据库升级。
|
||||
|
||||
默认策略如下:
|
||||
|
||||
| 消息延迟 | 普通记录保留率 | 非标记录保留率 |
|
||||
| --- | ---: | ---: |
|
||||
| 不大于 15 分钟 | 100% | 100% |
|
||||
| 大于 15、且小于 19.5 分钟 | 100% | 100% |
|
||||
| 19.5~小于 24 分钟 | 91% | 92% |
|
||||
| 24~小于 28.5 分钟 | 82% | 84% |
|
||||
| 28.5~小于 33 分钟 | 73% | 76% |
|
||||
| 33~小于 37.5 分钟 | 64% | 68% |
|
||||
| 37.5~小于 42 分钟 | 55% | 60% |
|
||||
| 42~小于 46.5 分钟 | 46% | 52% |
|
||||
| 46.5~小于 51 分钟 | 37% | 44% |
|
||||
| 51~小于 55.5 分钟 | 28% | 36% |
|
||||
| 55.5~小于 60 分钟 | 19% | 28% |
|
||||
| 不小于 60 分钟 | 10% | 20% |
|
||||
|
||||
默认前 15 分钟为免采样窗口。之后使用 `(60 分钟 - 15 分钟)÷ 10 = 4.5 分钟` 的阶梯宽度;
|
||||
达到 1 小时才使用最低保留率。
|
||||
|
||||
采样采用 `event_id` 的确定性哈希:同一策略版本下,同一消息重复处理时选择结果一致。规则计算始终执行,
|
||||
只有完成规则计算、确认是否产生告警并成功写入小时审计后,才执行丢弃。
|
||||
|
||||
## 写入顺序与故障行为
|
||||
|
||||
每个批次按以下顺序处理:
|
||||
|
||||
1. 完整规则计算并提交采样审计;
|
||||
2. 单独提交全部 `syslog_normal_alarm`;
|
||||
3. 写入被保留消息的 InfluxDB 原文;
|
||||
4. 写入被保留的 `syslog_normal_data` 和 `syslog_non_normal_message`。
|
||||
|
||||
InfluxDB 原文写入默认单次网络阶段最多等待 5 秒;发生依赖故障后,30 秒内快速跳过后续原文请求。启动
|
||||
健康检查失败、写入失败以及特殊 DLT 写入失败都只记录日志,不阻塞 Kafka 主消费进度。
|
||||
|
||||
## 升级后验证
|
||||
|
||||
查看消费和异常日志:
|
||||
|
||||
```bash
|
||||
docker logs --since 10m syslog-consumer-rule-dm 2>&1 \
|
||||
| grep -E 'Syslog批次完成|BACKLOG_SAMPLING|INFLUX_RAW_BYPASS|SYSLOG_CONTINUITY_LOSS' \
|
||||
| tail -100
|
||||
```
|
||||
|
||||
查看运行状态:
|
||||
|
||||
```text
|
||||
GET /xdrrule/api/syslog/backlog-sampling/status
|
||||
GET /xdrrule/api/syslog/raw-storage/metrics
|
||||
```
|
||||
|
||||
然后执行 `database/03-backlog-sampling-verify.sql` 的最后一段查询。没有延迟消息时,审计查询为空属于正常;
|
||||
发生积压后,应能按来源小时看到告警保存数、普通/非标实际保留率和原文丢弃数。
|
||||
|
||||
重点确认:
|
||||
|
||||
- `alarm_rows_saved` 始终等于 `alarm_rows_total`;
|
||||
- `audit_write_failures_total` 和 `audit_fallback_messages_total` 不持续增加;
|
||||
- InfluxDB 故障时 Kafka offset 仍继续推进,告警和达梦保留数据仍持续写入;
|
||||
- `raw_write_bypassed_messages_total` 增加表示原文旁路失败,不表示主消费停止。
|
||||
|
||||
## 回滚
|
||||
|
||||
紧急关闭采样可配置:
|
||||
|
||||
```yaml
|
||||
- SYSLOG_BACKLOG_SAMPLING_ENABLED=false
|
||||
```
|
||||
|
||||
重建 `syslog-consumer-rule` 容器后,普通、非标及原文恢复全量保留。也可回滚旧 JAR。无论采用哪种方式,
|
||||
都保留 `syslog_backlog_retention_hourly` 表,不要删除历史审计数据。
|
||||
@@ -0,0 +1,54 @@
|
||||
# v4 新增变量配置
|
||||
|
||||
配置文件:
|
||||
|
||||
```text
|
||||
syslog-consumer-rule/docker-compose/docker-compose-consumer-rule-prod.yaml
|
||||
```
|
||||
|
||||
在 `services.syslog-consumer-rule.environment` 中增加:
|
||||
|
||||
```yaml
|
||||
# 前15分钟全量保留,之后到1小时之间分10级降低保留率;告警始终全量保留。
|
||||
- SYSLOG_BACKLOG_SAMPLING_ENABLED=true
|
||||
- SYSLOG_BACKLOG_SAMPLING_START_LAG_MS=900000
|
||||
- SYSLOG_BACKLOG_SAMPLING_LAG_THRESHOLD_MS=3600000
|
||||
- SYSLOG_BACKLOG_SAMPLING_NORMAL_RETAIN_BPS=1000
|
||||
- SYSLOG_BACKLOG_SAMPLING_NON_NORMAL_RETAIN_BPS=2000
|
||||
- SYSLOG_BACKLOG_SAMPLING_DEGRADE_STEPS=10
|
||||
- SYSLOG_BACKLOG_SAMPLING_POLICY_VERSION=v2
|
||||
|
||||
# 小时审计最多等待 5 秒;失败后 60 秒内不重试,并回退全量保留。
|
||||
- SYSLOG_BACKLOG_SAMPLING_AUDIT_TIMEOUT_SECONDS=5
|
||||
- SYSLOG_BACKLOG_SAMPLING_AUDIT_RETRY_BACKOFF_MS=60000
|
||||
|
||||
# InfluxDB 原文写入失败时快速返回并继续主消费。
|
||||
- INFLUXDB_RAW_WRITE_REQUEST_TIMEOUT=5s
|
||||
- INFLUXDB_RAW_FAILURE_BACKOFF_MS=30000
|
||||
```
|
||||
|
||||
其中:
|
||||
|
||||
- `NORMAL_RETAIN_BPS` 和 `NON_NORMAL_RETAIN_BPS` 是达到延迟阈值后的最低保留万分比;`1000` 表示 10%,
|
||||
`2000` 表示 20%;
|
||||
- `START_LAG_MS=900000` 是15分钟免采样窗口,该时间内普通、非标及原文全部保留;
|
||||
- `LAG_THRESHOLD_MS=3600000` 是达到最低保留率的时间;扣除15分钟后,剩余45分钟由10级平均分配,
|
||||
每级4.5分钟;
|
||||
- `START_LAG_MS` 必须大于等于0并且小于 `LAG_THRESHOLD_MS`,配置非法时应用拒绝启动;
|
||||
- 修改起始延迟、结束阈值、最低保留率或级数时,必须同时修改 `POLICY_VERSION`,以便审计区分策略;
|
||||
- `AUDIT_TIMEOUT_SECONDS` 是单次达梦审计事务超时;审计失败时本批次全量保留;
|
||||
- `INFLUXDB_RAW_WRITE_REQUEST_TIMEOUT` 是连接、写入、读取各网络阶段的上限,不是整个批次的总超时;
|
||||
- `INFLUXDB_RAW_FAILURE_BACKOFF_MS` 是确认 InfluxDB 依赖故障后的快速跳过时间。
|
||||
|
||||
这些默认值已经写在 JAR 的 `application.properties` 中。现场只替换 JAR 时同样会默认开启采样;显式写入
|
||||
Compose 是为了便于后续核查和调整。启动新 JAR 前必须先创建
|
||||
`SYSLOG_BACKLOG_RETENTION_HOURLY`,否则应用会因审计失败回退全量保留,并周期性记录错误日志。
|
||||
|
||||
关闭采样只需设置:
|
||||
|
||||
```yaml
|
||||
- SYSLOG_BACKLOG_SAMPLING_ENABLED=false
|
||||
```
|
||||
|
||||
InfluxDB 非阻塞旁路不受通用的 `SYSLOG_FAILURE_CONTINUITY_ENABLED` 开关控制:InfluxDB 写入失败始终记录并
|
||||
放行,避免原文存储故障阻塞告警和后续 Kafka 消息。
|
||||
@@ -0,0 +1,21 @@
|
||||
-- v4 达梦升级预检:只读,不修改任何对象。
|
||||
-- 必须使用 syslog-consumer-rule 实际连接的达梦用户执行。
|
||||
|
||||
-- 首次升级应返回 0 行;如果返回 1 行,不要重复执行 02,直接执行 03 验证。
|
||||
SELECT table_name
|
||||
FROM user_tables
|
||||
WHERE table_name = 'SYSLOG_BACKLOG_RETENTION_HOURLY';
|
||||
|
||||
-- 首次升级应返回 0 行。
|
||||
SELECT constraint_name, constraint_type, status, table_name
|
||||
FROM user_constraints
|
||||
WHERE constraint_name IN (
|
||||
'PK_SYSLOG_BACKLOG_RET_HOURLY',
|
||||
'CK_SYSLOG_BACKLOG_RET_BPS'
|
||||
)
|
||||
ORDER BY constraint_name;
|
||||
|
||||
-- 首次升级应返回 0 行。
|
||||
SELECT index_name, table_name, uniqueness, status
|
||||
FROM user_indexes
|
||||
WHERE index_name = 'IDX_SYSLOG_BACKLOG_RET_UPDATED';
|
||||
@@ -0,0 +1,49 @@
|
||||
-- v4 达梦升级:创建 Kafka 积压分级采样的小时审计表。
|
||||
-- 仅在 01 预检确认目标对象均不存在时执行一次,不要重复执行。
|
||||
|
||||
CREATE TABLE syslog_backlog_retention_hourly (
|
||||
source_hour TIMESTAMP NOT NULL,
|
||||
source_topic VARCHAR2(255) NOT NULL,
|
||||
kafka_partition INT NOT NULL,
|
||||
policy_version VARCHAR2(64) NOT NULL,
|
||||
normal_retain_bps INT NOT NULL,
|
||||
non_normal_retain_bps INT NOT NULL,
|
||||
message_total BIGINT DEFAULT 0 NOT NULL,
|
||||
alarm_rows_total BIGINT DEFAULT 0 NOT NULL,
|
||||
alarm_rows_saved BIGINT DEFAULT 0 NOT NULL,
|
||||
normal_rows_total BIGINT DEFAULT 0 NOT NULL,
|
||||
normal_rows_saved BIGINT DEFAULT 0 NOT NULL,
|
||||
normal_rows_dropped BIGINT DEFAULT 0 NOT NULL,
|
||||
non_normal_rows_total BIGINT DEFAULT 0 NOT NULL,
|
||||
non_normal_rows_saved BIGINT DEFAULT 0 NOT NULL,
|
||||
non_normal_rows_dropped BIGINT DEFAULT 0 NOT NULL,
|
||||
raw_total BIGINT DEFAULT 0 NOT NULL,
|
||||
raw_saved BIGINT DEFAULT 0 NOT NULL,
|
||||
raw_dropped BIGINT DEFAULT 0 NOT NULL,
|
||||
min_lag_ms BIGINT DEFAULT 0 NOT NULL,
|
||||
max_lag_ms BIGINT DEFAULT 0 NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
updated_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
CONSTRAINT pk_syslog_backlog_ret_hourly PRIMARY KEY (
|
||||
source_hour, source_topic, kafka_partition, policy_version,
|
||||
normal_retain_bps, non_normal_retain_bps
|
||||
),
|
||||
CONSTRAINT ck_syslog_backlog_ret_bps CHECK (
|
||||
normal_retain_bps BETWEEN 0 AND 10000
|
||||
AND non_normal_retain_bps BETWEEN 0 AND 10000
|
||||
)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_syslog_backlog_ret_updated
|
||||
ON syslog_backlog_retention_hourly(updated_at);
|
||||
|
||||
COMMENT ON TABLE syslog_backlog_retention_hourly IS
|
||||
'Kafka积压分级采样小时审计;按来源小时、Topic、Partition和策略聚合';
|
||||
COMMENT ON COLUMN syslog_backlog_retention_hourly.source_hour IS
|
||||
'syslog-serve生成的receive_time所在小时(Asia/Shanghai)';
|
||||
COMMENT ON COLUMN syslog_backlog_retention_hourly.normal_retain_bps IS
|
||||
'普通标准化记录该级实际保留万分比,10000表示100%';
|
||||
COMMENT ON COLUMN syslog_backlog_retention_hourly.non_normal_retain_bps IS
|
||||
'非标记录该级实际保留万分比,10000表示100%';
|
||||
|
||||
COMMIT;
|
||||
@@ -0,0 +1,56 @@
|
||||
-- v4 Kafka 积压分级采样升级验证:只读。
|
||||
|
||||
-- 应返回 SYSLOG_BACKLOG_RETENTION_HOURLY 一行。
|
||||
SELECT table_name
|
||||
FROM user_tables
|
||||
WHERE table_name = 'SYSLOG_BACKLOG_RETENTION_HOURLY';
|
||||
|
||||
-- 应返回 22 个字段。
|
||||
SELECT column_id, column_name, data_type, nullable
|
||||
FROM user_tab_columns
|
||||
WHERE table_name = 'SYSLOG_BACKLOG_RETENTION_HOURLY'
|
||||
ORDER BY column_id;
|
||||
|
||||
-- 两个约束都应为 ENABLED。
|
||||
SELECT constraint_name, constraint_type, status
|
||||
FROM user_constraints
|
||||
WHERE constraint_name IN (
|
||||
'PK_SYSLOG_BACKLOG_RET_HOURLY',
|
||||
'CK_SYSLOG_BACKLOG_RET_BPS'
|
||||
)
|
||||
ORDER BY constraint_name;
|
||||
|
||||
-- 索引应为 VALID。
|
||||
SELECT index_name, uniqueness, status
|
||||
FROM user_indexes
|
||||
WHERE index_name = 'IDX_SYSLOG_BACKLOG_RET_UPDATED';
|
||||
|
||||
-- 结构验证后应能执行;首次建表且还未发生积压采样时返回 0。
|
||||
SELECT COUNT(*) AS audit_row_count
|
||||
FROM syslog_backlog_retention_hourly;
|
||||
|
||||
-- 查看每个来源小时的实际选择率。该值反映采样选择,不代表后续存储一定写入成功。
|
||||
-- 没有发生积压采样时,本查询返回空属于正常。
|
||||
SELECT
|
||||
source_hour,
|
||||
SUM(message_total) AS message_total,
|
||||
SUM(alarm_rows_total) AS alarm_rows_total,
|
||||
SUM(alarm_rows_saved) AS alarm_rows_saved,
|
||||
SUM(normal_rows_total) AS normal_rows_total,
|
||||
SUM(normal_rows_saved) AS normal_rows_saved,
|
||||
SUM(normal_rows_dropped) AS normal_rows_dropped,
|
||||
CASE WHEN SUM(normal_rows_total) = 0 THEN 1
|
||||
ELSE SUM(normal_rows_saved) * 1.0 / SUM(normal_rows_total) END AS normal_actual_rate,
|
||||
SUM(non_normal_rows_total) AS non_normal_rows_total,
|
||||
SUM(non_normal_rows_saved) AS non_normal_rows_saved,
|
||||
SUM(non_normal_rows_dropped) AS non_normal_rows_dropped,
|
||||
CASE WHEN SUM(non_normal_rows_total) = 0 THEN 1
|
||||
ELSE SUM(non_normal_rows_saved) * 1.0 / SUM(non_normal_rows_total) END AS non_normal_actual_rate,
|
||||
SUM(raw_total) AS raw_total,
|
||||
SUM(raw_saved) AS raw_saved,
|
||||
SUM(raw_dropped) AS raw_dropped,
|
||||
MIN(min_lag_ms) AS min_lag_ms,
|
||||
MAX(max_lag_ms) AS max_lag_ms
|
||||
FROM syslog_backlog_retention_hourly
|
||||
GROUP BY source_hour
|
||||
ORDER BY source_hour DESC;
|
||||
Reference in New Issue
Block a user