perf(syslog): 统计异步化并按采样保留率自适应调整业务批量
- 入口统计改用独立 Kafka 消费组,移除主消费同步统计写库 - DIRECT 模式入库计数改为事务提交后异步投递,取消事实事务内统计 Outbox 写入 - 采样审计、告警分钟桶通知改为后台处理,异常不阻断主消费或回滚告警 - RAW 基础业务批量默认 500,按保留率动态扩大,上限 3000 - 限制业务块字节数及规则任务数量,保留告警全量处理和整次 poll 完成后提交 - 细化 SLOW_SYSLOG_BATCH,补充批次关联、线程排队、数据库执行及提交耗时 - 更新 v4 升级说明,明确异步统计损失风险及现场验证方法 验证:JDK 8 构建成功,232 项测试通过。 升级:复用现有表和 Kafka Topic,无新增建表或建 Topic 脚本要求。
This commit is contained in:
@@ -84,6 +84,16 @@ syslog.raw-consumer.enabled=true
|
||||
syslog.raw-listener.concurrency=${SYSLOG_RAW_LISTENER_CONCURRENCY:3}
|
||||
# 端到端批次耗时达到该阈值时,打印业务各阶段及 Kafka offset 同步提交耗时;0 表示关闭。
|
||||
syslog.slow-batch.threshold-ms=${SYSLOG_SLOW_BATCH_THRESHOLD_MS:500}
|
||||
# 普通业务基础批量500(保留旧配置名);不再表示底层poll上限。已有同名环境变量仍覆盖基础值。
|
||||
# 目标业务批量=ceil(基础条数*10000/max(普通保留万分比,非标保留万分比)),并受下面3000上限限制。
|
||||
syslog.raw-listener.max-poll-records=${SYSLOG_RAW_LISTENER_MAX_POLL_RECORDS:500}
|
||||
# 底层RAW max.poll.records固定为此值;无积压时也可能poll到3000,再按500分块,全部处理后才ACK。
|
||||
# 基础值必须大于0且不超过上限;Retry/大日志/独立统计不采用此自适应策略。
|
||||
syslog.raw-listener.adaptive-max-records=${SYSLOG_RAW_LISTENER_ADAPTIVE_MAX_RECORDS:3000}
|
||||
# 大批次按 Kafka value 序列化字节拆成16MiB业务块,全部完成后提交本次poll;单条不会切断。
|
||||
syslog.raw-listener.processing-batch-max-bytes=${SYSLOG_RAW_PROCESSING_BATCH_MAX_BYTES:16777216}
|
||||
# 每个业务块只向共享规则线程池提交8个worker,避免2000条对应2000个排队任务。
|
||||
syslog.normalization.workers-per-batch=${SYSLOG_NORMALIZATION_WORKERS_PER_BATCH:8}
|
||||
# 连续性优先:特殊/系统性异常优先写 DLT;即使 DLT 失败也记录告警并推进原 offset,避免阻塞分区。
|
||||
syslog.failure-continuity.enabled=${SYSLOG_FAILURE_CONTINUITY_ENABLED:true}
|
||||
# DLT 故障时最多快速等待 1 秒;首次失败后整批直接记录并放行。
|
||||
@@ -146,7 +156,7 @@ syslog.large-reliability.consumer-group-id=${spring.kafka.consumer.group-id}-lar
|
||||
syslog.large-reliability.consumer.enabled=true
|
||||
|
||||
|
||||
# 调试修改:普通 Kafka Consumer 单次最多拉取条数。如需改为2000,将 500 改为 2000。
|
||||
# 通用消费者(如Retry)的上限;RAW底层上限用adaptive-max-records,业务基础值用syslog.raw-listener.max-poll-records。
|
||||
# 使用 prod profile 时 application-prod.properties 中存在同名配置,必须同步修改,否则 prod 值会覆盖本项。
|
||||
spring.kafka.consumer.max-poll-records=500
|
||||
spring.kafka.consumer.properties.max.poll.interval.ms=900000
|
||||
@@ -163,6 +173,8 @@ spring.task.scheduling.pool.size=10
|
||||
|
||||
# 标准化告警事实与迟到重放通知使用同一个达梦事务。
|
||||
analysis.late-replay.outbox-enabled=${ANALYSIS_LATE_REPLAY_OUTBOX_ENABLED:true}
|
||||
# 告警提交后后台写分钟桶的事务超时;不在主消费线程等待。JDBC/连接池自身超时仍独立生效。
|
||||
analysis.late-replay.notify-timeout-seconds=${ANALYSIS_LATE_REPLAY_NOTIFY_TIMEOUT_SECONDS:5}
|
||||
|
||||
# 日志配置
|
||||
logging.level.com.common.schedule=INFO
|
||||
@@ -240,11 +252,18 @@ spring.datasource.hikari.validation-timeout=5000
|
||||
spring.datasource.hikari.leak-detection-threshold=30000
|
||||
spring.datasource.hikari.pool-name=HikariPool-SyslogConsumer-rule
|
||||
spring.datasource.hikari.auto-commit=false
|
||||
# DIRECT 不再写逐事实 change_log;默认只在事实事务追加一条批次 Outbox,日统计异步投影。
|
||||
# DIRECT 连续消费优先:事实事务不再写统计Outbox/日统计表,提交后通过有界内存队列异步发布统计。
|
||||
# 首次部署 DIRECT 前必须先执行 08/09/10/11 脚本并按设计文档排空旧 pending。
|
||||
stats.write-mode=DIRECT
|
||||
stats.incremental.capture-enabled=false
|
||||
stats.ingress-metadata.enabled=true
|
||||
# 入口统计独立消费原始Topic,直接聚合写统计表;主消费不再写入口Outbox。
|
||||
# 各节点必须使用同一组名,且不得与业务主消费组相同。
|
||||
stats.ingress-metadata.group-id=${STATS_INGRESS_GROUP_ID:${spring.kafka.consumer.group-id}-ingress-v1}
|
||||
stats.ingress-metadata.large-group-id=${STATS_INGRESS_LARGE_GROUP_ID:${stats.ingress-metadata.group-id}-large}
|
||||
stats.ingress-metadata.max-poll-records=${STATS_INGRESS_MAX_POLL_RECORDS:2000}
|
||||
# 新组默认从Kafka仍保留的最早消息开始,确保不跳过历史接收时间;已有offset继续原位置。
|
||||
stats.ingress-metadata.auto-offset-reset=${STATS_INGRESS_AUTO_OFFSET_RESET:earliest}
|
||||
stats.incremental.read-enabled=true
|
||||
stats.incremental.transaction-timeout-seconds=45
|
||||
stats.device-receive.change-capture-enabled=false
|
||||
@@ -275,10 +294,13 @@ stats.materialization.concurrency-retry-backoff-ms=${STATS_MATERIALIZATION_CONCU
|
||||
stats.materialization.reconcile-initial-delay-ms=${STATS_MATERIALIZATION_RECONCILE_INITIAL_DELAY_MS:30000}
|
||||
stats.materialization.reconcile-interval-ms=${STATS_MATERIALIZATION_RECONCILE_INTERVAL_MS:60000}
|
||||
|
||||
# Fact transactions append one aggregated durable event instead of locking the daily projection rows.
|
||||
# A dedicated single-lane Kafka consumer applies device/rule/collector projection deltas and then
|
||||
# emits the existing idempotent business-materialization dirty keys.
|
||||
# 事实提交后只做内存offer,独立线程发送到统计Kafka;满队列/进程退出可能少统计,不阻碍事实消费。
|
||||
# enabled=false 会跳过统计并记录损失,绝不回退为同步统计写库。正常保持true。
|
||||
# 旧Outbox继续后台排空,applied表仍用于统计事件去重,不要删表。
|
||||
stats.projection-async.enabled=${STATS_PROJECTION_ASYNC_ENABLED:true}
|
||||
# 队列最多1000个批次聚合事件;含正在重试事件的聚合分组总数最多50000,限制内存占用。
|
||||
stats.projection-async.memory-queue-capacity=${STATS_PROJECTION_MEMORY_QUEUE_CAPACITY:1000}
|
||||
stats.projection-async.memory-max-pending-groups=${STATS_PROJECTION_MEMORY_MAX_PENDING_GROUPS:50000}
|
||||
stats.projection-async.outbox-table=${STATS_PROJECTION_OUTBOX_TABLE:stats_projection_outbox}
|
||||
stats.projection-async.applied-table=${STATS_PROJECTION_APPLIED_TABLE:stats_projection_applied_event}
|
||||
stats.projection-async.topic=${STATS_PROJECTION_TOPIC:${spring.kafka.consumer.topic}.STATS.PROJECTION}
|
||||
|
||||
Reference in New Issue
Block a user