ํฐ์คํ ๋ฆฌ ๋ทฐ
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
- nestjs directory
- Spring Async
- sequelize
- nestjs module
- typeorm ์ฐ๊ฒฐ
- node.js backend
- Request_Limit_Exceeded
- backend-framework
- ์๊ณ ๋ฆฌ์ฆ
- docker mysql
- Promise error
- nestjs/cli
- Promise bulk
- NestJS
- nestjs configService
- Spring
- nestjs project
- @nestjs/config
- typeorm
- nestjs typeorm
- foreignkey
- nestjs config
- DeferredResult
- nestjs doc
- JavaScript
- node.js
- android
- ๊ธฐ์์ฒญAPI
- ๋น๋๊ธฐ ์์ฒญ
- ํ๋ก๊ทธ๋๋จธ์ค
| ์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
|---|---|---|---|---|---|---|
| 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 |