update finalize ykc offline fix baseline

This commit is contained in:
Guoqs
2026-03-21 11:15:33 +08:00
parent 4aafe089ff
commit b0cfcf40fa
4 changed files with 106 additions and 18 deletions

View File

@@ -165,7 +165,11 @@ public class PileChannelEntity {
if (!StringUtils.equals(currentChannelId, expectedChannelId)) {
return false;
}
return manager.remove(pileSn, currentCtx);
boolean removed = manager.remove(pileSn, currentCtx);
if (removed) {
channelIdToPileSnMap.remove(expectedChannelId);
}
return removed;
}
public static List<String> getPileSnListSnapshot() {

View File

@@ -27,7 +27,7 @@ public class ThreadPoolConfig {
// 最大可创建的线程数
private final int maxPoolSize = 128; // 突发时翻倍,避免过多上下文切换
// 队列最大长度 (优化:增大队列容量以应对桩端消息高峰)
// 队列最大长度
private final int queueCapacity = 5000; // 桩消息短时堆积时提供缓冲,防止直接拒绝
// 线程池维护线程所允许的空闲时间
@@ -51,7 +51,6 @@ public class ThreadPoolConfig {
/**
* 线程池
* 优化:使用 DiscardOldestPolicy 避免阻塞调用者线程(如 Netty IO 线程)
*/
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
@@ -61,8 +60,8 @@ public class ThreadPoolConfig {
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveSeconds);
// 线程池对拒绝任务(无线程可用)的处理策略
// 优化DiscardOldestPolicy 丢弃最老的任务,避免阻塞调用者线程
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
// 关键链路任务不能静默丢弃,回退为调用方执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setThreadNamePrefix(threadNamePrefix);
executor.setWaitForTasksToCompleteOnShutdown(true);
// log.info("threadPoolTaskExecutor创建成功");

View File

@@ -64,19 +64,16 @@ public class HeartbeatRequestHandler extends AbstractYkcHandler {
String connectorStatus = BytesUtil.binary(connectorStatusByte, 16);
// log.info("桩号:{}, 枪号:{}, 枪状态:{}", pileSn, pileConnectorNum, connectorStatus);
// 优化:先构建并返回心跳应答,不阻塞心跳回复
// 先构建心跳应答,再同步刷新最后通信时间和连接映射,保证离线确认链路及时收敛
byte[] flag = Constants.zeroByteArray;
byte[] messageBody = Bytes.concat(pileSnByte, pileConnectorNumByte, flag);
byte[] response = getResult(ykcDataProtocol, messageBody);
// 优化所有其他操作Redis、数据库完全异步化不阻塞心跳回复
// 将 saveLastTimeAndCheckChannel 和 updateStatus 都改为异步执行
saveLastTimeAndCheckChannel(pileSn, channel);
// 数据库状态更新继续异步,避免把心跳回包链路拖长
CompletableFuture.runAsync(() -> {
try {
// 异步保存连接时间并检查通道Redis 操作)
saveLastTimeAndCheckChannel(pileSn, channel);
// 异步更新状态(数据库操作)
String frameType = BytesUtil.bcd2Str(ykcDataProtocol.getFrameType());
pileBasicInfoService.updateStatus(frameType, pileSn, pileConnectorNum, connectorStatus, null);
} catch (Exception e) {

View File

@@ -88,8 +88,11 @@ created_at: 2026-03-21T08:48:24+08:00
### YKC-001
- 优先级P0
- 状态:todo
- 状态done
- 目标将云快充连接保活从“30 秒空闲直接断开”改为“允许短时抖动,按连续丢心跳或宽限期判定断链”。
- 当前进展:
- 已按第一批止血方案落地为 `15s tick + 连续 3 次 READER_IDLE 才关闭`
- 已补 `idleCount / lastFrameType / lastReceiveAt / lastSerialNumber / disconnectReason` 连接属性。
- 修改文件:
- `/Users/guoqiusi/Workspace/jsowell-charger-web/jsowell-netty/src/main/java/com/jsowell/netty/server/yunkuaichong/NettyServerChannelInitializer.java`
- `/Users/guoqiusi/Workspace/jsowell-charger-web/jsowell-netty/src/main/java/com/jsowell/netty/server/yunkuaichong/NettyServerHandler.java`
@@ -106,8 +109,11 @@ created_at: 2026-03-21T08:48:24+08:00
### YKC-002
- 优先级P0
- 状态:todo
- 状态done
- 目标:增加“断链宽限期”,避免瞬断立刻将枪口置离线、订单置异常。
- 当前进展:
- 已落地 `60s` 离线确认宽限期。
- 已引入 `pile_pending_disconnect``pile_offline_confirmed` 标记,并在恢复通信后自动清理。
- 修改文件:
- `/Users/guoqiusi/Workspace/jsowell-charger-web/jsowell-netty/src/main/java/com/jsowell/netty/service/yunkuaichong/impl/YKCBusinessServiceImpl.java`
- `/Users/guoqiusi/Workspace/jsowell-charger-web/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java`
@@ -124,8 +130,11 @@ created_at: 2026-03-21T08:48:24+08:00
### YKC-003
- 优先级P0
- 状态:todo
- 状态:in_progress
- 目标:补齐连接生命周期日志,支持“凌晨离线”专项排查。
- 当前进展:
- 已补空闲告警、连续空闲关闭、异常断链、宽限恢复、正式离线确认等主链路日志。
- `LoginRequestHandler` / `UploadRealTimeMonitorHandler` 维度的专项日志尚未单独补齐。
- 修改文件:
- `/Users/guoqiusi/Workspace/jsowell-charger-web/jsowell-netty/src/main/java/com/jsowell/netty/server/yunkuaichong/NettyServerHandler.java`
- `/Users/guoqiusi/Workspace/jsowell-charger-web/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/HeartbeatRequestHandler.java`
@@ -142,8 +151,11 @@ created_at: 2026-03-21T08:48:24+08:00
### YKC-004
- 优先级P0
- 状态:todo
- 状态done
- 目标:修复 channel 映射清理不完整的问题,避免旧连接残留。
- 当前进展:
- 已补 `removeByPileSnAndChannelId()` 安全删除。
- 已补 `channelId -> pileSn` 反向映射维护,并修复删除时的脏映射残留问题。
- 修改文件:
- `/Users/guoqiusi/Workspace/jsowell-charger-web/jsowell-netty/src/main/java/com/jsowell/netty/service/yunkuaichong/impl/YKCBusinessServiceImpl.java`
- `/Users/guoqiusi/Workspace/jsowell-charger-web/jsowell-common/src/main/java/com/jsowell/common/enums/ykc/PileChannelEntity.java`
@@ -159,8 +171,11 @@ created_at: 2026-03-21T08:48:24+08:00
### YKC-005
- 优先级P1
- 状态:todo
- 状态:in_progress
- 目标:将桩离线判定从“任意枪状态为离线即整桩离线”改为“最近通信时间 + 枪状态 + 宽限期”的综合判定。
- 当前进展:
- 已完成 `checkPileOffLine()` 优先识别 `PILE_OFFLINE_CONFIRMED` 标记。
- 仍未重写 `getPileStatus/getPileStatusV2` 的整桩聚合规则,暂按第一批止血范围保留现状。
- 修改文件:
- `/Users/guoqiusi/Workspace/jsowell-charger-web/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileConnectorInfoServiceImpl.java`
- 设计要点:
@@ -195,8 +210,12 @@ created_at: 2026-03-21T08:48:24+08:00
### YKC-007
- 优先级P1
- 状态:todo
- 状态done
- 目标:补每日自动对时,降低跨天时钟漂移的影响。
- 当前进展:
- 已新增 `jsowellTask.dailyProofreadTimeForYkcV160()`
- 已补 `0x56` 下发记录和 `0x55` 应答记录。
- 待上线时补 Quartz 任务配置。
- 修改文件:
- `/Users/guoqiusi/Workspace/jsowell-charger-web/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/YKCPushCommandServiceImpl.java`
- `/Users/guoqiusi/Workspace/jsowell-charger-web/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/TimeCheckSettingResponseHandler.java`
@@ -319,6 +338,23 @@ created_at: 2026-03-21T08:48:24+08:00
- 订单异常处理若改为延迟确认,需防止漏处理真正断电或断网导致的异常订单。
- 双实现收敛前,所有改动应明确打在老 Handler 链路上,避免误改新 Strategy 无法生效。
## 当前进度快照
- 更新时间2026-03-21 11:14:17 +0800
- `done`
- `YKC-001`
- `YKC-002`
- `YKC-004`
- `YKC-007`
- `in_progress`
- `YKC-003`
- `YKC-005`
- `todo`
- `YKC-006`
- `YKC-008`
- `YKC-009`
- `YKC-010`
## 进度记录模板
```md
@@ -338,6 +374,58 @@ created_at: 2026-03-21T08:48:24+08:00
- 备注/风险:
```
## 最终上线注意项
- 本次建议作为一个整体上线,包含:
- 第一批凌晨离线止血。
- `YKC-007` 云快充 1.6 每日自动对时。
- 当前最终基线以“离线判定正确性优先”为准,同时保留必要性能优化:
- 保留 `EchoServerHandler` 绑定 `businessGroup`
- 保留 `PileChannelEntity``channelId -> pileSn` 反向映射。
- 保留 `NettyServerHandler` 的消息处理耗时监控。
- 不采用“心跳全异步 + 公共线程池 DiscardOldestPolicy”组合。
- 已确认的最终收口原则:
- `HeartbeatRequestHandler``saveLastTimeAndCheckChannel()` 必须同步执行,保证任意上行立即刷新 `PILE_LAST_CONNECTION`,并立即清除 `PILE_PENDING_DISCONNECT / PILE_OFFLINE_CONFIRMED`
- `HeartbeatRequestHandler``updateStatus()` 继续异步执行,避免数据库操作拖长心跳回包链路。
- `ThreadPoolConfig.threadPoolTaskExecutor` 保持 `CallerRunsPolicy`,避免关键任务被静默丢弃。
- `PileChannelEntity.removeByPileSnAndChannelId()` 必须同步清理反向映射,避免旧连接脏数据残留。
### Quartz 配置建议
- 新增每日对时任务:
- `invokeTarget`: `jsowellTask.dailyProofreadTimeForYkcV160()`
- 不建议把任务压在 `00:00` 整点,建议放到低峰时段,例如 `03:15`
- 每日对时任务默认只扫描“当前有活连接的云快充 1.6 桩”,并按小间隔逐台发送,避免凌晨集中打满链路。
### 上线后重点观察
- 是否还出现“凌晨批量掉线后立刻落离线”的情况。
- 是否能看到 `pile_pending_disconnect` 在恢复通信后于宽限期内被清除。
- 是否出现“正式离线确认”日志明显下降。
- 是否能看到 `0x56` 下发记录与 `0x55` 应答记录。
- 是否持续出现 `【性能警告】` 日志堆积。
### 建议回归项
- 连续触发 1 次、2 次、3 次 `READER_IDLE`
- 预期仅第 3 次关闭连接。
- 第 3 次空闲关闭后 60 秒内重连:
- 预期不落 `OFF_NETWORK`,不改订单异常。
- 第 3 次空闲关闭后 60 秒内未恢复:
- 预期才正式落离线。
- 手工执行一次 `jsowellTask.dailyProofreadTimeForYkcV160()`
- 预期仅对在线云快充 1.6 桩发对时。
- 检查 `TimeCheckSettingResponseHandler`
- 预期能记录 `0x55` 对时应答及桩端回传时间。
### 编译验证记录
- 已执行:
- `mvn -pl jsowell-quartz,jsowell-netty -am -DskipTests compile`
- `mvn -pl jsowell-netty,jsowell-framework,jsowell-common -am -DskipTests compile`
- 结果:
- 通过。
## 当前建议
- 先以第一批任务为本周主线,尽快止住凌晨离线误判。