1.41
This commit is contained in:
parent
d16b1d59ed
commit
f619654b1a
@ -134,28 +134,45 @@ public class ThreadPoolConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* 审计事件处理线程池 - 使用虚拟线程(Java 21+)
|
||||
* 审计事件处理线程池 - 使用传统线程池(更稳定可靠)
|
||||
*
|
||||
* ⚠️ 为什么使用虚拟线程?
|
||||
* 1. 审计事件处理是**I/O密集型**任务(写日志、写数据库)
|
||||
* 2. 虚拟线程在I/O阻塞时不占用OS线程,资源消耗极低
|
||||
* 3. 审计事件量可能很大,虚拟线程支持高并发处理
|
||||
* 4. 独立线程池避免与业务线程池竞争资源
|
||||
* ⚠️ 为什么不使用虚拟线程?
|
||||
* 1. 审计任务量不大,不需要虚拟线程的高并发能力
|
||||
* 2. 审计日志是关键数据,传统线程池的异常处理更成熟可靠
|
||||
* 3. 传统线程池有队列缓冲,可以防止突发流量
|
||||
* 4. 传统线程池的监控和调试工具更完善
|
||||
* 5. 虚拟线程在异常处理方面还不够成熟,可能导致异常被吞掉
|
||||
*
|
||||
* 💡 场景:
|
||||
* - 异步记录用户操作审计日志
|
||||
* - 写入审计数据库
|
||||
* - 发送审计事件到消息队列
|
||||
*
|
||||
* 🎯 解决问题:
|
||||
* - 修复 "More than one TaskExecutor bean found" 警告
|
||||
* - 确保审计事件处理不受其他业务线程池影响
|
||||
* 🎯 线程池配置:
|
||||
* - 核心线程数:2(审计任务通常不多)
|
||||
* - 最大线程数:4(足够处理突发流量)
|
||||
* - 队列容量:1000(缓冲突发的审计事件)
|
||||
* - 拒绝策略:CallerRunsPolicy(确保审计日志不丢失)
|
||||
* - 优雅关闭:等待60秒让审计任务完成
|
||||
*/
|
||||
@Bean("auditTaskExecutor")
|
||||
public SimpleAsyncTaskExecutor auditTaskExecutor() {
|
||||
SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor("audit-virtual-");
|
||||
executor.setVirtualThreads(true);
|
||||
executor.setConcurrencyLimit(-1); // 无限制,支持大量并发审计事件
|
||||
public AsyncTaskExecutor auditTaskExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(2); // 审计任务不多,2个核心线程足够
|
||||
executor.setMaxPoolSize(4); // 最大4个线程处理突发流量
|
||||
executor.setQueueCapacity(1000); // 较大的队列,缓冲突发审计事件
|
||||
executor.setThreadNamePrefix("audit-");
|
||||
executor.setKeepAliveSeconds(60);
|
||||
|
||||
// ⚠️ 关键:使用CallerRunsPolicy确保审计日志不丢失
|
||||
// 如果线程池满了,由调用线程执行,保证审计日志一定被记录
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
|
||||
// ⚠️ 优雅关闭:等待审计任务完成
|
||||
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||
executor.setAwaitTerminationSeconds(60);
|
||||
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
|
||||
|
||||
@ -13,14 +13,24 @@ public class AuditEventListener {
|
||||
@Async("auditTaskExecutor")
|
||||
@EventListener
|
||||
public void handleAuditEvent(AuditEvent event) {
|
||||
// 这里可以将审计信息保存到数据库或发送到日志系统
|
||||
log.info("Audit: {} performed {} on {} (ID: {}) at {}, detail: {}",
|
||||
event.getMetadata().getOperator(),
|
||||
event.getMetadata().getAction(),
|
||||
event.getMetadata().getEntityType(),
|
||||
event.getMetadata().getEntityId(),
|
||||
event.getMetadata().getTimestamp(),
|
||||
event.getMetadata().getDetail()
|
||||
);
|
||||
try {
|
||||
// 这里可以将审计信息保存到数据库或发送到日志系统
|
||||
log.info("Audit: {} performed {} on {} (ID: {}) at {}, detail: {}",
|
||||
event.getMetadata().getOperator(),
|
||||
event.getMetadata().getAction(),
|
||||
event.getMetadata().getEntityType(),
|
||||
event.getMetadata().getEntityId(),
|
||||
event.getMetadata().getTimestamp(),
|
||||
event.getMetadata().getDetail()
|
||||
);
|
||||
} catch (Exception e) {
|
||||
// ⚠️ 关键修复:捕获并记录所有异常,防止异常被@Async吞掉
|
||||
log.error("Failed to handle audit event: operator={}, action={}, entityType={}, entityId={}",
|
||||
event.getMetadata().getOperator(),
|
||||
event.getMetadata().getAction(),
|
||||
event.getMetadata().getEntityType(),
|
||||
event.getMetadata().getEntityId(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,24 +12,15 @@ INSERT INTO system_release (
|
||||
)
|
||||
VALUES (
|
||||
'system', NOW(), 'system', NOW(), 1, 0,
|
||||
1.41, 'ALL', NOW(),
|
||||
1.42, 'ALL', NOW(),
|
||||
'【后端】
|
||||
|
||||
- ServerLogStreamStrategy: 修复tail -f命令重复问题,数据库logQueryCommand已包含完整命令,只需追加-n 行数参数
|
||||
- K8sLogStreamStrategy: 统一sessionId命名规范,修复日志输出不一致问题
|
||||
- DockerLogStreamStrategy: 统一sessionId命名规范
|
||||
- AbstractLogStreamWebSocketHandler: 在sendLogLine(), sendStatus(), sendError()方法中添加synchronized(session)保护
|
||||
- 说明:synchronized(session)锁粒度是每个session对象,不同用户的session互不影响,性能影响可忽略
|
||||
- Strategy实现中统一使用logStreamSessionId参数名(仅用于日志输出)
|
||||
- 区分webSocketId(原始ID)和logStreamSessionId(增强ID)
|
||||
- 优化cleanupSession()方法,先关闭Shell输入输出流强制中断阻塞的read操作
|
||||
- 增强readSSHOutput()和readSSHError()的异常处理和线程中断检查
|
||||
【前端】
|
||||
- Monaco Editor替换XTerm.js
|
||||
- 架构重构 - 移除LogViewerWindow中间层
|
||||
- LogViewerWindow违反单一职责原则
|
||||
- 后端协议对齐(LOG/STATUS/ERROR消息类型)
|
||||
- K8S应用重复连接
|
||||
- 智能自动滚动
|
||||
- 新日志强制滚动影响用户体验
|
||||
- 修改类型定义(types.ts),将k8sNamespaceId: number和k8sDeploymentId: number改为k8sNamespaceName: string和k8sDeploymentName: string
|
||||
- 更新K8sRuntimeConfig组件,改为基于name进行选择和匹配,通过namespaceName查找对应的namespace ID来加载Deployment列表
|
||||
- 调整RuntimeConfigSection和TeamApplicationDialog组件的props传递和表单数据结构,确保使用name字段进行数据绑定和提交
|
||||
- 同步更新TeamApplicationManageDialog的保存逻辑,向后端提交name字段而非ID
|
||||
',
|
||||
0, NULL, NULL, 0
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user