Skip to content

Commit b028cdf

Browse files
committed
feat: AsyncConfig 스레드 풀 용량 증가 및 모니터링 추가
- 스레드 풀 보수적 증가: core 5→10, max 10→20, queue 100→200 - CallerRunsPolicy 적용으로 큐 초과 시 graceful degradation - 스레드 풀 모니터링 추가 (30초마다, 큐 80% 이상 시 경고) - 스레드 이름 prefix 변경: 'async-event-' - 새 설정을 반영하도록 AsyncConfigTest 업데이트
1 parent ff2a269 commit b028cdf

2 files changed

Lines changed: 56 additions & 13 deletions

File tree

apps/commerce-api/src/main/java/com/loopers/config/AsyncConfig.java

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,49 @@
44
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
55
import org.springframework.context.annotation.Bean;
66
import org.springframework.context.annotation.Configuration;
7+
import org.springframework.retry.annotation.EnableRetry;
78
import org.springframework.scheduling.annotation.AsyncConfigurer;
89
import org.springframework.scheduling.annotation.EnableAsync;
10+
import org.springframework.scheduling.annotation.Scheduled;
911
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
1012

1113
import java.util.concurrent.Executor;
14+
import java.util.concurrent.ThreadPoolExecutor;
1215

1316
/**
1417
* 비동기 처리 설정
1518
* @Async 메서드를 위한 ThreadPool 및 예외 처리 구성
19+
* @Retryable 메서드를 위한 재시도 설정
1620
*/
1721
@Slf4j
1822
@Configuration
1923
@EnableAsync
24+
@EnableRetry
2025
public class AsyncConfig implements AsyncConfigurer {
2126

2227
/**
23-
* 비동기 작업용 ThreadPool 설정
24-
* - corePoolSize: 기본 스레드 수 (5개)
25-
* - maxPoolSize: 최대 스레드 수 (10개)
26-
* - queueCapacity: 대기 큐 크기 (100개)
28+
* 비동기 작업용 ThreadPool 설정 (보수적 증가)
29+
* - corePoolSize: 기본 스레드 수 (10개)
30+
* - maxPoolSize: 최대 스레드 수 (20개)
31+
* - queueCapacity: 대기 큐 크기 (200개)
2732
* - threadNamePrefix: 스레드 이름 접두사
33+
*
34+
* 처리량: 초당 200개 이벤트 즉시 처리 + 400개 큐 대기 = 총 600개 버퍼
2835
*/
2936
@Bean(name = "taskExecutor")
3037
@Override
3138
public Executor getAsyncExecutor() {
3239
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
33-
executor.setCorePoolSize(5);
34-
executor.setMaxPoolSize(10);
35-
executor.setQueueCapacity(100);
36-
executor.setThreadNamePrefix("async-");
40+
executor.setCorePoolSize(10); // 5 → 10
41+
executor.setMaxPoolSize(20); // 10 → 20
42+
executor.setQueueCapacity(200); // 100 → 200
43+
executor.setThreadNamePrefix("async-event-");
3744
executor.setWaitForTasksToCompleteOnShutdown(true);
38-
executor.setAwaitTerminationSeconds(30);
45+
executor.setAwaitTerminationSeconds(60); // 30 → 60
46+
47+
// 큐 초과 시 거부 정책: 호출한 스레드에서 실행
48+
executor.setRejectedExecutionHandler(new java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy());
49+
3950
executor.initialize();
4051
return executor;
4152
}
@@ -58,4 +69,36 @@ public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
5869
public ThreadPoolTaskExecutor taskExecutor() {
5970
return (ThreadPoolTaskExecutor) getAsyncExecutor();
6071
}
72+
73+
/**
74+
* 스레드 풀 모니터링 (30초마다)
75+
* - active: 현재 실행 중인 스레드 수
76+
* - queue: 큐에 대기 중인 작업 수
77+
* - completed: 완료된 작업 수
78+
*/
79+
@Scheduled(fixedDelay = 30000)
80+
public void monitorThreadPool() {
81+
ThreadPoolTaskExecutor executor = taskExecutor();
82+
ThreadPoolExecutor pool = executor.getThreadPoolExecutor();
83+
84+
int activeCount = pool.getActiveCount();
85+
int queueSize = pool.getQueue().size();
86+
long completedTaskCount = pool.getCompletedTaskCount();
87+
long totalTaskCount = pool.getTaskCount();
88+
89+
log.info("[ThreadPool Monitoring] active={}, queue={}, completed={}, total={}",
90+
activeCount, queueSize, completedTaskCount, totalTaskCount);
91+
92+
// 큐가 80% 이상 차면 경고
93+
if (queueSize > 160) { // 200의 80%
94+
log.warn("[ThreadPool Warning] Queue is {}% full! (size: {})",
95+
(queueSize * 100 / 200), queueSize);
96+
}
97+
98+
// 활성 스레드가 최대치에 근접하면 경고
99+
if (activeCount >= 18) { // 20의 90%
100+
log.warn("[ThreadPool Warning] Active threads near max! (active: {})",
101+
activeCount);
102+
}
103+
}
61104
}

apps/commerce-api/src/test/java/com/loopers/config/AsyncConfigTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ class AsyncConfigTest {
5353

5454
// then
5555
assertThat(executor).isNotNull();
56-
assertThat(executor.getCorePoolSize()).isEqualTo(5);
57-
assertThat(executor.getMaxPoolSize()).isEqualTo(10);
58-
assertThat(executor.getQueueCapacity()).isEqualTo(100);
59-
assertThat(executor.getThreadNamePrefix()).isEqualTo("async-");
56+
assertThat(executor.getCorePoolSize()).isEqualTo(10);
57+
assertThat(executor.getMaxPoolSize()).isEqualTo(20);
58+
assertThat(executor.getQueueCapacity()).isEqualTo(200);
59+
assertThat(executor.getThreadNamePrefix()).isEqualTo("async-event-");
6060
}
6161

6262
@Component

0 commit comments

Comments
 (0)