refactor(ingress): 移除 G1 窗口补偿扫描与迟到到达检测
实际负载不足 10 条/秒,G1 属过度防御。删除迟到到达检测机制、 existingIds 接口、PipelineCounters 字段、lateDetect 配置, 以及文档中 CLM-1/CLM-2 声明与 G1 缺口索引。
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package com.gzzn.omms.msgexchange.infra.metrics
|
||||
|
||||
import jakarta.inject.Singleton
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
|
||||
/**
|
||||
* 管道运行期的**进程内**计数。
|
||||
@@ -12,26 +11,4 @@ import java.util.concurrent.atomic.AtomicLong
|
||||
* 注意:计数在重启后归零。需要跨重启的累计值应由指标后端聚合,不在这里做持久化。
|
||||
*/
|
||||
@Singleton
|
||||
class PipelineCounters {
|
||||
private val holeAgedOut = AtomicLong(0)
|
||||
private val lateArrivalDetected = AtomicLong(0)
|
||||
|
||||
/** 水位因空洞超过老化阈值而放行(判定为永久空洞)的次数。 */
|
||||
fun holeAgedOutIncrement() {
|
||||
holeAgedOut.incrementAndGet()
|
||||
}
|
||||
|
||||
fun holeAgedOutCount(): Long = holeAgedOut.get()
|
||||
|
||||
/**
|
||||
* "迟到到达"检测命中的**不同**消息 ID 数(ACM2-41 阶段 0)。
|
||||
*
|
||||
* 含义:该 ID 曾被判定为永久空洞并放行,之后却真的出现在信箱里——即上游提交晚于水位推进。
|
||||
* 阶段 0 只计数与告警,**不会**补入队;因此这个值 > 0 表示"确有迟到发生,需要与库方对契约"。
|
||||
*/
|
||||
fun lateArrivalDetectedIncrement() {
|
||||
lateArrivalDetected.incrementAndGet()
|
||||
}
|
||||
|
||||
fun lateArrivalDetectedCount(): Long = lateArrivalDetected.get()
|
||||
}
|
||||
class PipelineCounters
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.time.Duration
|
||||
* - `msgx.pipeline.backfill.abandoned`:已放弃自动回填的条数(**非 0 需人工对账**)
|
||||
* - `msgx.pipeline.backfill.oldest_unmarked_seconds`:最老一条仍待自动回填的年龄
|
||||
* - `msgx.pipeline.watermark.lag`:水位落后信箱最新 ID 的距离
|
||||
* - `msgx.pipeline.hole.aged_out.total`:永久空洞放行次数
|
||||
* - `msgx.pipeline.job.heartbeat_age_seconds`:距上一次作业 tick 完成的秒数(未跑过为 -1)
|
||||
* - `msgx.pipeline.job.last_failure_age_seconds`:距最近一次作业 tick 失败的秒数(从未失败为 -1)
|
||||
* - `msgx.pipeline.job.ticks.total` / `msgx.pipeline.job.failures.total`:作业 tick 完成/抛错次数
|
||||
@@ -44,7 +43,6 @@ class PipelineMetrics(
|
||||
private val backlogs: BacklogSnapshotProvider,
|
||||
private val cursor: BeanProvider<InboxCursorRepository>,
|
||||
private val mailbox: BeanProvider<CminmsgInboxRepository>,
|
||||
private val counters: PipelineCounters,
|
||||
private val activity: JobActivity,
|
||||
private val clock: Clock,
|
||||
) {
|
||||
@@ -71,15 +69,6 @@ class PipelineMetrics(
|
||||
if (watermark != null && maxId != null) (maxId - watermark).toDouble() else -1.0
|
||||
}.strongReference(true).register(registry)
|
||||
|
||||
Gauge.builder("msgx.pipeline.hole.aged_out.total", counters) { it.holeAgedOutCount().toDouble() }
|
||||
.strongReference(true)
|
||||
.register(registry)
|
||||
|
||||
// 迟到到达检测命中数(阶段 0 只观测):> 0 表示上游提交确实晚于水位推进,需要与库方对契约。
|
||||
Gauge.builder("msgx.pipeline.late_arrival.detected.total", counters) { it.lateArrivalDetectedCount().toDouble() }
|
||||
.strongReference(true)
|
||||
.register(registry)
|
||||
|
||||
// 作业心跳与扫描积压:作业线程是回填的唯一驱动,停摆必须能被 /metrics 与 /health 看见。
|
||||
Gauge.builder("msgx.pipeline.job.heartbeat_age_seconds", activity) { a ->
|
||||
a.snapshot().lastTickAt?.let { Duration.between(it, clock.instant()).seconds.toDouble() } ?: -1.0
|
||||
|
||||
@@ -353,12 +353,6 @@ interface CminmsgInboxRepository {
|
||||
/** 信箱当前最小 ID,空表返回 null;切流播种用它推算 `W = MIN(ID) − 1`。 */
|
||||
fun minId(): Long?
|
||||
|
||||
/**
|
||||
* 批量查询这些 ID 里哪些**当前存在于信箱**。
|
||||
* 只用于"迟到到达"检测(被放行的空洞 ID 后来是否真的出现),不读大字段。
|
||||
*/
|
||||
fun existingIds(msgIds: Collection<Long>): Set<Long>
|
||||
|
||||
/**
|
||||
* 把处理标记写回信箱,并且**只写还是空标记的行**:库里已有值时不覆盖、不回退,
|
||||
* 重复调用没有副作用。结果明确区分本次写入、已有标记和信箱行缺失。
|
||||
|
||||
-14
@@ -86,20 +86,6 @@ class JdbcCminmsgInboxRepository(
|
||||
rs.getLong("min_id").takeIf { !rs.wasNull() }
|
||||
}
|
||||
|
||||
override fun existingIds(msgIds: Collection<Long>): Set<Long> {
|
||||
if (msgIds.isEmpty()) return emptySet()
|
||||
val out = linkedSetOf<Long>()
|
||||
// 分块避免 IN 列表过长(迟到检测一次最多查 late-detect-batch 个)。
|
||||
msgIds.chunked(200).forEach { chunk ->
|
||||
val placeholders = chunk.joinToString(",") { "?" }
|
||||
ds.query(
|
||||
"SELECT CMINMSGS_ID FROM cminmsgs WHERE CMINMSGS_ID IN ($placeholders)",
|
||||
{ ps -> chunk.forEachIndexed { i, id -> ps.setLong(i + 1, id) } },
|
||||
) { rs -> rs.getLong("CMINMSGS_ID") }.forEach { out += it }
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
/**
|
||||
* 只更新还是空标记的行,所以重复调用不会覆盖库里已有的值;
|
||||
* 影响 0 行时再查一次主键,区分“已有标记”和“信箱行缺失”;后者不能记为回填成功。
|
||||
|
||||
@@ -484,8 +484,6 @@ class StubInbox(private val clock: Clock = Clock.systemUTC()) : CminmsgInboxRepo
|
||||
|
||||
override fun minId(): Long? = raws.keys.minOrNull()
|
||||
|
||||
override fun existingIds(msgIds: Collection<Long>): Set<Long> = msgIds.filter { raws.containsKey(it) }.toSet()
|
||||
|
||||
/** 只写还没有标记的行,并区分已有标记与行缺失。 */
|
||||
override fun markProcessedIfUnmarked(msgId: Long, value: String): MailboxMarkResult {
|
||||
if (!raws.containsKey(msgId)) return MailboxMarkResult.MISSING
|
||||
|
||||
Reference in New Issue
Block a user