feat(syslog): 增加 WAL 与分 IP 接入诊断
- 每分钟保存 WAL 全局状态和分 IP 接收统计,历史保留 7 天 - 记录接收、WAL 落盘、Kafka ACK、过滤、背压及丢弃数量 - 增加 wal_max_pending_bytes 和 wal_admission_unavailable 指标 - 增加 TCP pending 当前值及进程内峰值统计 - 网络异常后同一 IP 恢复接收时打印恢复日志 - 提供当前状态及按日期查询诊断历史的接口 - 连接关闭时清理 TCP pending 计数并停止无效重试 - 增加相关单元测试和现场排查文档
This commit is contained in:
+25
-3
@@ -1,6 +1,7 @@
|
||||
package com.haobang.dispatch;
|
||||
|
||||
import com.haobang.config.AppProperties;
|
||||
import com.haobang.diagnostics.SyslogIpMetricsRegistry;
|
||||
import com.haobang.wal.SyslogWalRecord;
|
||||
import com.haobang.wal.SyslogWalService;
|
||||
import com.kafka.kafkaProducer;
|
||||
@@ -8,6 +9,7 @@ import com.netty.SyslogMessageHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
@@ -51,6 +53,7 @@ public class SyslogWalDispatcher {
|
||||
private final LongAdder retryCount = new LongAdder();
|
||||
private final LongAdder largeDispatched = new LongAdder();
|
||||
private final AtomicLong inflight = new AtomicLong();
|
||||
private SyslogIpMetricsRegistry ipMetrics;
|
||||
|
||||
private Semaphore permits;
|
||||
private ByteBudget byteBudget;
|
||||
@@ -71,6 +74,11 @@ public class SyslogWalDispatcher {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
void setIpMetrics(SyslogIpMetricsRegistry ipMetrics) {
|
||||
this.ipMetrics = ipMetrics;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void start() throws Exception {
|
||||
validateConfiguration();
|
||||
@@ -157,6 +165,10 @@ public class SyslogWalDispatcher {
|
||||
walService.recordTerminal(record, resolution.getType().name(), resolution.getReason());
|
||||
} else {
|
||||
terminalDropped.increment();
|
||||
if (ipMetrics != null) {
|
||||
ipMetrics.recordTerminalDropped(record.getSourceIp(), record.getSourcePort(),
|
||||
record.getProtocol(), resolution.getDevice(), resolution.getReason());
|
||||
}
|
||||
}
|
||||
terminalFiltered.increment();
|
||||
markComplete(record);
|
||||
@@ -200,6 +212,10 @@ public class SyslogWalDispatcher {
|
||||
.whenComplete((delivery, failure) -> {
|
||||
if (failure == null) {
|
||||
kafkaAcked.increment();
|
||||
if (ipMetrics != null) {
|
||||
ipMetrics.recordKafkaAck(record.getSourceIp(), record.getSourcePort(),
|
||||
record.getProtocol(), resolution.getDevice());
|
||||
}
|
||||
if (large) largeDispatched.increment();
|
||||
markComplete(record);
|
||||
} else {
|
||||
@@ -214,6 +230,9 @@ public class SyslogWalDispatcher {
|
||||
|
||||
private void scheduleRetry(SyslogWalRecord record, int attempt, String stage, Throwable failure) {
|
||||
retryCount.increment();
|
||||
if (ipMetrics != null) {
|
||||
ipMetrics.recordDispatchRetry(record.getSourceIp(), record.getSourcePort(), record.getProtocol());
|
||||
}
|
||||
long retries = retryCount.sum();
|
||||
if (attempt == 1 || retries % 100 == 0) {
|
||||
log.warn("WAL 事件投递失败,将保留原 event_id 重试: eventId={}, sequence={}, stage={}, "
|
||||
@@ -261,18 +280,21 @@ public class SyslogWalDispatcher {
|
||||
|
||||
private void logStatus() {
|
||||
if (!running.get()) return;
|
||||
log.info("Syslog WAL状态: networkReceived={}, appended={}, admissionOversized={}, walPendingApprox={}, walPendingBytes={}, walQueue={}/{}, durableSequence={}, "
|
||||
log.info("Syslog WAL状态: networkReceived={}, appended={}, admissionOversized={}, admissionUnavailable={}, "
|
||||
+ "walPendingApprox={}, walPendingBytes={}/{}, walQueue={}/{}, durableSequence={}, "
|
||||
+ "checkpointSequence={}, kafkaInflight={}, kafkaInflightBytes={}, kafkaAcked={}, largeDispatched={}, "
|
||||
+ "terminalRecordEnabled={}, terminalFiltered={}, terminalDropped={}, "
|
||||
+ "retry={}, tcpPauseTotal={}, udpDropped={}, deviceCacheSize={}, deviceCacheHits={}, "
|
||||
+ "retry={}, tcpPauseTotal={}, tcpPendingFrames={}/{}, udpDropped={}, deviceCacheSize={}, deviceCacheHits={}, "
|
||||
+ "deviceCacheMisses={}",
|
||||
SyslogMessageHandler.getNetworkReceivedCount(), walService.getAppendedCount(),
|
||||
walService.getOversizedCount(), walService.getPendingRecordsApprox(), walService.getPendingAppendBytes(),
|
||||
walService.getOversizedCount(), walService.getUnavailableCount(),
|
||||
walService.getPendingRecordsApprox(), walService.getPendingAppendBytes(), walService.getMaxPendingBytes(),
|
||||
walService.getQueueSize(), walService.getQueueCapacity(), walService.getDurableSequence(),
|
||||
walService.getCheckpointSequence(), inflight.get(), byteBudget == null ? 0L : byteBudget.used(),
|
||||
kafkaAcked.sum(), largeDispatched.sum(), properties.isSyslogDispatchTerminalRecordEnabled(),
|
||||
terminalFiltered.sum(), terminalDropped.sum(),
|
||||
retryCount.sum(), SyslogMessageHandler.getTcpPauseCount(),
|
||||
SyslogMessageHandler.getTcpPendingFramesCurrent(), SyslogMessageHandler.getTcpPendingFramesMax(),
|
||||
SyslogMessageHandler.getUdpDroppedCount(), deviceResolver.getCacheSize(),
|
||||
deviceResolver.getHitCount(), deviceResolver.getMissCount());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user