添加异步线程池配置.

This commit is contained in:
lijiahang
2023-07-11 11:00:46 +08:00
parent 646b73a7a3
commit 0890c47871
9 changed files with 248 additions and 9 deletions

View File

@@ -1,8 +1,15 @@
package com.orion.ops.framework.common.config;
import com.orion.ops.framework.common.thread.ThreadPoolMdcTaskExecutor;
import com.orion.spring.SpringHolder;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 应用配置类
@@ -11,7 +18,9 @@ import org.springframework.context.annotation.Bean;
* @version 1.0.0
* @since 2023/6/20 10:34
*/
@EnableAsync
@AutoConfiguration
@EnableConfigurationProperties(ThreadPoolConfig.class)
public class OrionCommonAutoConfiguration {
/**
@@ -22,4 +31,31 @@ public class OrionCommonAutoConfiguration {
return new SpringHolder.ApplicationContextAwareStore();
}
/**
* 支持 MDC 的异步线程池
* <p>
* {@code @Async("asyncExecutor")}
*
* @return 异步线程池
*/
@Primary
@Bean(name = "asyncExecutor")
public TaskExecutor asyncExecutor(ThreadPoolConfig config) {
ThreadPoolMdcTaskExecutor executor = new ThreadPoolMdcTaskExecutor();
executor.setCorePoolSize(config.getCorePoolSize());
executor.setMaxPoolSize(config.getMaxPoolSize());
executor.setQueueCapacity(config.getQueueCapacity());
executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
executor.setAllowCoreThreadTimeOut(true);
executor.setThreadNamePrefix("async-task-");
// 设置等待所有任务执行结束再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
// 以确保应用最后能够被关闭
executor.setAwaitTerminationSeconds(60);
// 调用者调用拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}

View File

@@ -0,0 +1,44 @@
package com.orion.ops.framework.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 线程池配置类
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/7/10 15:49
*/
@Data
@ConfigurationProperties(prefix = "orion.thread.pool")
public class ThreadPoolConfig {
/**
* 核心线程数量
*/
private int corePoolSize;
/**
* 最大线程数量
*/
private int maxPoolSize;
/**
* 队列容量
*/
private int queueCapacity;
/**
* 活跃时间
*/
private int keepAliveSeconds;
public ThreadPoolConfig() {
this.corePoolSize = 8;
this.maxPoolSize = 16;
this.queueCapacity = 200;
this.keepAliveSeconds = 300;
}
}

View File

@@ -15,7 +15,7 @@ public enum ErrorCode implements CodeInfo {
BAD_REQUEST(400, "参数验证失败"),
UNAUTHORIZED(401, "会话过期"),
UNAUTHORIZED(401, "当前认证信息已失效, 请重新登录"),
FORBIDDEN(403, "无操作权限"),

View File

@@ -11,6 +11,10 @@ import com.alibaba.ttl.TransmittableThreadLocal;
*/
public class TraceIdHolder {
public static final String TRACE_ID_HEADER = "trace-id";
public static final String TRACE_ID_MDC = "tid";
private TraceIdHolder() {
}

View File

@@ -0,0 +1,33 @@
package com.orion.ops.framework.common.thread;
import com.orion.ops.framework.common.utils.ThreadMdcUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
/**
* 自动注入 MDC 异步线程池
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/7/10 15:16
*/
public class ThreadPoolMdcTaskExecutor extends ThreadPoolTaskExecutor {
@Override
public void execute(Runnable task) {
super.execute(ThreadMdcUtils.wrap(task));
}
@Override
public <T> Future<T> submit(Callable<T> task) {
return super.submit(ThreadMdcUtils.wrap(task));
}
@Override
public Future<?> submit(Runnable task) {
return super.submit(ThreadMdcUtils.wrap(task));
}
}

View File

@@ -0,0 +1,84 @@
package com.orion.ops.framework.common.utils;
import com.orion.ops.framework.common.meta.TraceIdHolder;
import org.slf4j.MDC;
import java.util.Map;
import java.util.concurrent.Callable;
/**
* 多线程下 MDC 工具类
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/7/10 14:55
*/
public class ThreadMdcUtils {
private ThreadMdcUtils() {
}
/**
* 设置 MDC traceId
*/
public static void setTraceIdIfAbsent() {
if (MDC.get(TraceIdHolder.TRACE_ID_MDC) == null) {
MDC.put(TraceIdHolder.TRACE_ID_MDC, TraceIdHolder.get());
}
}
/**
* 设置线程 MDC 上下文
*
* @param callable callable
* @param <T> T
* @return callable
*/
public static <T> Callable<T> wrap(Callable<T> callable) {
// 获取当前线程 MDC 上下文
Map<String, String> callerContext = MDC.getCopyOfContextMap();
return () -> {
if (callerContext == null) {
MDC.clear();
} else {
MDC.setContextMap(callerContext);
}
// 设置 traceId
setTraceIdIfAbsent();
// 执行线程并且清理MDC
try {
return callable.call();
} finally {
MDC.clear();
}
};
}
/**
* 设置线程 MDC 上下文
*
* @param runnable runnable
* @return callable
*/
public static Runnable wrap(Runnable runnable) {
// 获取当前线程 MDC 上下文
Map<String, String> callerContext = MDC.getCopyOfContextMap();
return () -> {
//
if (callerContext == null) {
MDC.clear();
} else {
MDC.setContextMap(callerContext);
}
// 设置 traceId
setTraceIdIfAbsent();
// 执行线程并且清理MDC
try {
runnable.run();
} finally {
MDC.clear();
}
};
}
}

View File

@@ -0,0 +1,35 @@
{
"groups": [
{
"name": "orion.thread.pool",
"type": "com.orion.ops.framework.common.config.ThreadPoolConfig",
"sourceType": "com.orion.ops.framework.common.config.ThreadPoolConfig"
}
],
"properties": [
{
"name": "orion.thread.pool.core-pool-size",
"type": "java.lang.Integer",
"description": "核心线程数量",
"defaultValue": "8"
},
{
"name": "orion.thread.pool.max-pool-size",
"type": "java.lang.Integer",
"description": "最大线程数量.",
"defaultValue": "16"
},
{
"name": "orion.thread.pool.queue-capacity",
"type": "java.lang.Integer",
"description": "队列容量.",
"defaultValue": "200"
},
{
"name": "orion.thread.pool.keep-alive-seconds",
"type": "java.lang.Integer",
"description": "活跃时间.",
"defaultValue": "300"
}
]
}

View File

@@ -2,6 +2,7 @@ package com.orion.ops.launch.controller;
import com.orion.ops.framework.common.annotation.RestWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -13,6 +14,7 @@ import org.springframework.web.bind.annotation.RestController;
* @version 1.0.0
* @since 2023/6/19 17:08
*/
@Tag(name = "launch - 启动服务")
@RestWrapper
@RestController
@RequestMapping("/server/bootstrap")

View File

@@ -33,16 +33,17 @@ springdoc:
knife4j:
enable: false
logging:
printer:
mode: ROW
orion:
logging:
printer:
mode: ROW
crypto:
aes:
enabled: true
working-mode: ECB
padding-mode: PKCS5_PADDING
# 加密秘钥
secret-key: uQeacXV8b3isvKLK
generator-key: true
thread:
pool:
core-pool-size: 8
max-pool-size: 16
queue-capacity: 200
keep-alive-seconds: 300