ํฐ์คํ ๋ฆฌ ๋ทฐ
Spring MVC์ ๋น๋๊ธฐ์ฒ๋ฆฌ (ThreadPoolTaskExecutor ์ฌ์ฉ)
๋๋์ด๋ฐ๐พ 2023. 8. 22. 11:47Spring MVC์์ ํ๋ก์ธ์ค๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋๊ธฐ์ ์ฒ๋ฆฌ๋ก ์ด๋ฃจ์ด์ง๋๋ค.
์ฝ๋ ํ์คํ์ค ์ฐจ๋ก๋๋ก ์คํ์ด ์๋ฃ๋ ํ ๋์ด๊ฐ ์ ์๋ค๋ ๋ป์ด์ฃ . ๋ณดํต ์ด๊ฑธ Blocking ์ด๋ผ๊ณ ํ๊ณ ๋ฐ๋๊ฐ ๋๋ ๋ง์ Non-Blocking ์ด๋ผ๊ณ ํฉ๋๋ค. ์ฝ๋๊ฐ ์ฐจ๋ก๋๋ก ์คํ๋๊ธฐ ๋๋ฌธ์ ์ฝ๋ ์คํ์ ๋ฐ๋ฅธ ๊ฒฐ๊ณผ ๊ฐ์ ๋ณด๋๊ฒ ๋ช ํํ ์ฅ์ ์ด ์์ต๋๋ค.
Node.js๋ก ๊ฐ๋ฐ์ ์ข ํด์ค๋ค๋ณด๋ (Node.js๋ ๋ฐ๋๋ก ๋น๋๊ธฐ์ฒ๋ฆฌ๊ฐ ๊ธฐ๋ณธ ์ปจ์ ์ ๋๋ค.) Async์ ๋ํ ์ฉ์ด์ ๋ ๋์ด๊ฐ์ Spring ์ด๋ ธํ ์ด์ ์ค @Async ์ด๋ ธํ ์ด์ ์ ๋จผ์ ๋์ด ๊ฐ์ต๋๋ค. ์ด๋ ธํ ์ด์ ํ๋๋ง ์ถ๊ฐํ๋ฉด ๋ด๊ฐ ์ํ๋๊ฒ ๋๋ค?
@Async
@Async๋ Spring ํ๋ ์์ํฌ์์ ๋น๋๊ธฐ์ ์ธ ๋ฉ์๋ ์คํ์ ์ง์ํ๊ธฐ ์ํ ์ด๋ ธํ ์ด์ ์ ๋๋ค. ์ด ์ด๋ ธํ ์ด์ ์ ๋ฉ์๋์ ๋ถ์ด๋ฉด ํด๋น ๋ฉ์๋๋ ๋ณ๋์ ์ฐ๋ ๋์์ ์คํ๋๋ฉฐ, ํธ์ถํ ์ฐ๋ ๋๋ ๋ฉ์๋๊ฐ ์๋ฃ๋ ๋๊น์ง ๋ธ๋กํน๋์ง ์์ต๋๋ค. @Async๋ฅผ ์ฌ์ฉํ๋ฉด ๋๊ธฐ์ ์ธ ๋ฐฉ์์ด ์๋ ๋น๋๊ธฐ์ ์ธ ๋ฐฉ์์ผ๋ก ๋ฉ์๋๋ฅผ ์คํํ ์ ์์ต๋๋ค.
๋ฉ์๋์ ๊ทธ๋ฅ ์ด๋ ธํ ์ด์ ๋ง ๋ถ์ด๋ฉด Async ๋ฉ์๋๊ฐ ๋๋ ๊ฒ์ธ๊ฐ? ํ์ง๋ง @Async๋ฅผ ์ฌ์ฉํ ๋ ์ฃผ์ํ ์ ์ ์ด ์ด๋ ธํ ์ด์ ๋ Thread pool์ ์ฌ์ฉํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋ฌด๋ถ๋ณํ๊ฒ ์ฌ์ฉํ๋ฉด ์ค๋ฒํค๋๊ฐ ๋ฐ์ํ ์๋ ์๊ณ , ์คํ๋ง์ ํ๋ก์ ๋งค์ปค๋์ฆ์ ํตํด ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ๊ตฌํ๋๊ธฐ ๋๋ฌธ์ @Async ๋ฉ์๋๋ ๊ฐ์ ํด๋์ค ๋ด์์ ํธ์ถ๋๋ฉด ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋์ง ์์ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ AOP ํ๋ก์๊ฐ ์ ์ฉ๋์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ ๊ฐ์ ๊ฒฝ์ฐ๋ Spring MVC ํ๋ก์ ํธ์ ๊ธฐ๋ณธ์ ์ผ๋ก Filter๋ฅผ ์ฌ์ฉํ๊ณ ์๋๋ฐ ์ ๋ด์ฉ๋๋ฌธ์ ์ ๋๋ก ์๋ํ์ง ์๋ ๋ถ๋ถ์ ํ์ธํ๊ณ ๋ฐ๋ก ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ฐพ์๋ณด์์ต๋๋ค.
ThreadPoolTaskExecutor
์คํ๋ง์์ ์ ๊ณตํด์ฃผ๋ ํด๋์ค๋ก ์ฐ๋ ๋ํ์ ์ด์ฉํ์ฌ ๋ฉํฐ์ฐ๋ ๋ ๊ตฌํ์ ์ฝ๊ฒ ํด์ฃผ๋ ํด๋์ค์ ๋๋ค.
์ผ๋จ ์ ๊ฐ ์๋ํ ๋ถ๋ถ์ API ํธ์ถ ์์ ๋ด๋ถ ์ฒ๋ฆฌ์ ์๊ด์์ด ๋น ๋ฅด๊ฒ ์๋ต ๊ฐ์ ์ฃผ๋๊ฑธ ์๊ฐํ์ต๋๋ค.
๊ทธ๋ฌ๊ธฐ์ํด์ ๋ถํ๊ฐ ํฐ Service ๋ฉ์๋์ ๋ํ Async ์ฒ๋ฆฌ๊ฐ ํ์ํ๊ณ , ์๋์๊ฐ์ด ์ฒ๋ฆฌํ์ต๋๋ค.
AsyncConfig.class
: ์ฐ๋ ๋ํ์ ์ฌ์ฉํ๊ธฐ ์ํ custom ์ค์ ์ ํ๋ ํด๋์ค์ ๋๋ค.
@Configuration
public class AsyncConfig {
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10); // ์ฐ๋ ๋ํ์ ๊ธฐ๋ณธ ํฌ๊ธฐ
executor.setMaxPoolSize(50); // ์ฐ๋ ๋ํ์ ์ต๋ ํฌ๊ธฐ
executor.setQueueCapacity(100); // ์์
ํ ํฌ๊ธฐ
executor.setThreadNamePrefix("Custom-Async-"); // ์ฐ๋ ๋ ์ด๋ฆ ์ ๋์ฌ ์ค์
executor.initialize();
return executor;
}
}
Controller์ฝ๋
: ์๋น์ค ๋ฉ์๋๋ฅผ ๋ฐฑ๊ทธ๋ผ์ด๋ ๋ก์ง์ผ๋ก ์์ ํ์๊ณ , DeferredResult ๊ฐ์ฒด์ ๋น๋๊ธฐ๋ก์ง์ ๋ํ ๊ฒฐ๊ณผ ๊ฐ์ ์ ์ฅํ ์ ์์ต๋๋ค.
@RequiredArgsConstructor
public class AlarmController {
private final AlarmService alarmService;
@Qualifier("taskExecutor")
private final ThreadPoolTaskExecutor taskExecutor;
@PostMapping(value = "/{id}/send")
public Response<Map<String,Object>> immediatelyPush(
HttpServletRequest req,
@PathVariable("id") Long id
) {
try {
// DeferredResult<Response<Map<String, Object>>> deferredResult = new DeferredResult<>();
taskExecutor.submit(() -> {
// ๋น๋๊ธฐ๋ก ์คํ๋๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ๋ก์ง
alarmService.immediatelyPush(id);
// deferredResult.setResult(new Response<>(ResultCode.REGISTER_SUCCESS));
// deferredResult.setResult(new Response<>(ResultCode.REGISTER_FAIL));
});
return new Response<>(ResultCode.REGISTER_SUCCESS);
} catch (Exception e) {
return new Response<>(ResultCode.REGISTER_FAIL);
}
}
}
์ด๋ ๊ฒ๋๋ฉด ์๋น์ค ๋ฉ์๋์ ๋ํ ๋ถ๋ถ์ด ์คํ์๋ฃ๋์ง์์๋ ์ฆ์ response๋ฅผ ๋๊ฒจ์ฃผ๊ฒ ๋ฉ๋๋ค. ๋ฌผ๋ก responseํ์๋ Spring Application ์์๋ ํด๋น ๋ก์ง์ด ์คํ์ค์ด๊ฒ ๋ฉ๋๋ค.
'spring๐' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Spring boot์์ Http request ๋น๋๊ธฐ ์์ฒญํ๊ธฐ (0) | 2023.10.26 |
---|
- Total
- Today
- Yesterday
- Promise bulk
- Promise error
- android
- ๊ธฐ์์ฒญAPI
- docker mysql
- sequelize
- backend-framework
- @nestjs/config
- NestJS
- nestjs typeorm
- nestjs doc
- foreignkey
- nestjs configService
- Spring
- DeferredResult
- ํ๋ก๊ทธ๋๋จธ์ค
- nestjs config
- ์๊ณ ๋ฆฌ์ฆ
- nestjs project
- Spring Async
- nestjs module
- ๋น๋๊ธฐ ์์ฒญ
- nestjs/cli
- node.js backend
- node.js
- nestjs directory
- JavaScript
- typeorm
- Request_Limit_Exceeded
- typeorm ์ฐ๊ฒฐ
์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |