[Spring] ๋น๋๊ธฐ ์์ ๊ณผ ๋ชจ๋ํฐ๋ง์ ์ํ TaskExecutor, TaskScheduler ๊ธฐ๋ณธ
Spring Framework๋ TaskExecutor ์ธํฐํ์ด์ค์ TaskScheduler ์ธํฐํ์ด์ค๋ก Task(์์ )์ ๋น๋๊ธฐ ์คํ๊ณผ ์ค์ผ์ค๋ง์ ๋ํ ์ถ์ํ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๋ฐ ๊ฒ์ด ํ์ํ ์ด์ ๋ ๋ฌด์์ผ๊น์?
๊ธฐ๋ณธ์ ์ผ๋ก Spring์ Multi-Thread ๋ฐฉ์์ ์ฌ์ฉํ๋ฉฐ Singleton Pattern์ ์ด์ฉํด ๋ชจ๋ Bean๋ค์ ๊ณต์ ํ์ฌ ์ฌ์ฉํฉ๋๋ค. ํ์ง๋ง ์ด๋ ๊ธฐ๋ณธ์ ์ผ๋ก API๋ฅผ ํธ์ถํ๋ ๊ณผ์ ์ Blockingํ์ง ์๊ณ ๋ค์ค ์ฌ์ฉ์๊ฐ ์์ฒญ์ ๋ฐ์ ์ ์๋๋ก ์ฒ๋ฆฌํ๋ค๋ ๋ป์ ๋๋ค. ๋ฐ๋ผ์ ์ฐ๋ฆฌ๊ฐ API ํธ์ถ ์ดํ Bean ๋ด ์ด๋ค ํน์ ์์ ์ ๋ํ ๋น๋๊ธฐ ์คํ์ ๋ณด์ฅ๋์ง ์์ต๋๋ค.
TaskExecutor
TaskExecutor๋ Spring 2.0์์ ๋ฑ์ฅํ ๋น๋๊ธฐ ์คํ ์ถ์ํ ์ธํฐํ์ด์ค๋ก JDK 1.5์์ Thread Pool์ ๋ํ ๊ฐ๋ ์ผ๋ก ์ฌ์ฉํ๋ Executor๋ฅผ ์์ํ ๊ฒ์ ๋๋ค.
๊ทธ๊ฒ์ ์ฌ์ฉํ๋ ๊ตฌํ์ฒด๊ฐ ์ค์ ๋ก ํ(Pool)์ด๋ผ๋ ๋ณด์ฅ์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ค์ ๋ก Executor๋ ์ฑ๊ธ ์ค๋ ๋(Single-Thread)๊ฐ ๋ ์๋ ์๊ณ ๋๊ธฐํ๊ฐ ๋ ์๋ ์์ต๋๋ค.
Spring์ TaskExecutor๊ฐ ๋ณ๋์ ์ถ์ํ ์ธํฐํ์ด์ค๋ก ์กด์ฌํ๋ ์ด์ ๋ ์ค๋ ๋ ํ์ ๋ํ ์ถ์ํ๊ฐ ํ์ํ ๊ณณ์ ๋ค๋ฅธ ์คํ๋ง ์ปดํฌ๋ํธ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด์ ์ ๋๋ค. ์ด๋ฅผํ ๋ฉด ApplicationEventMulticaster๋ JSM์ AbstractMessageListenerContainer, Quartz ํตํฉ ์ปดํฌ๋ํธ๋ค์ ๋ชจ๋ ์ค๋ ๋ ํ์ TaskExecutor ์ถ์ํ๋ฅผ ๊ตฌํํ ๊ตฌํ์ฒด๋ค์ ๋๋ค.
ํ์ง๋ง ๋น(Bean) ๋ด์์ ์ค๋ ๋ ํ ๋์(๋น๋๊ธฐ ์์ )์ด ํ์ํ๋ค๋ฉด ์ด ๋ํ ์์ ์ ์๊ตฌ ์ฌํญ์ ๋ง๊ฒ TaskExecutor๋ฅผ ์ด์ฉํ ์ ์์ต๋๋ค.
TaskExecutor ์ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ ์์ ๊ฐ์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ํ๊ณ ์ ํ๋ ์์ ์ ๋ฐ์๋ค์ด๋ Submitter, ๊ทธ๋ฆฌ๊ณ ๊ทธ ์์ ์ ์คํํ ์ค์ ์์ ์ Task, ๊ทธ ์์ ์ ์คํํ Thread๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค.
Java์ ์ค๋ ๋ ๊ฐ์ฒด๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์์ง๋ง ์ฐ๋ฆฌ๊ฐ ์ด๋ ๊ฒ Thread Pool์ ์ฌ์ฉํด์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํด์ผํ๋ ์ด์ ๋ ๋ฐ๋ก ์ค๋ ๋๋ฅผ ์์ฑํ๋ ์๊ฐ์ ์ธ ๋น์ฉ์ ์ค์ด๊ณ , ์ค๋ ๋๋ฅผ ์์ฑํ๋ ๋ฐ ๋ฐ์ํ ์๋ ์๋ OOM(OutOfMemory) ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด์ ์ ๋๋ค.
TaskExecutor ์ข ๋ฅ
Spring ๋ฐฐํฌ๋ณธ์๋ ์๋ง์ TaskExecutor ๊ตฌํ์ฒด๋ค์ด ์๊ธฐ ๋๋ฌธ์ ์ง์ ๊ตฌํํด์ผ ํ ์ผ์ ๊ฑฐ์ ์์ต๋๋ค. ๊ทธ ์ค ์ผ๋ถ ๋ช ๊ฐ์ง๋ง ๋ค๋ค๋ณด์๋ฉด...
- SimpleAsyncTaskExecutor
์ด๋ค ์ค๋ ๋๋ ์ฌ์ฌ์ฉํ์ง ์๊ณ , ํธ์ถ ๋๋ง๋ค ์๋ก์ด ์ค๋ ๋๋ฅผ ์์ฑํ๋ Executor.
ํ์ง๋ง ๋์ ์ ๊ทผ ์ ํ(concurrency limit)์ ํตํด ์ ํ ์๋ฅผ ๋์ด์๋ฉด ๋น ๊ณต๊ฐ์ด ์๊ธธ ๋๊น์ง ๋ชจ๋ ์์ฒญ์ ๋ฐ์ง ์์. - SyncTaskExecutor
์์ ์ ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ์ง ์๊ณ , ์์ ์ ํธ์ถํ ์ค๋ ๋์ ์ถ๊ฐ๋๋ Executor
Multi-thread ๋ฐฉ์์ด ์๋. - ConcurrentTaskExecutor
์ด ๊ตฌํ์ฒด๋ Spring์ TaskExecutor๊ฐ ์๋ Java์ java.util.concurrent.Executor์ ๋ํผ๋ก Spring๊ณผ ๊ฐ์ด ์ฐ๋ ค๋ฉด ๋ถ๊ฐ์ ์ผ๋ก ๊ด๋ จ๋ ๋ฌด์ธ๊ฐ๋ฅผ ๊ตฌํํด์ผ ํ๋ค๋ ๋จ์ ์ด ์๋ค.
์ด์ ๋์์ผ๋ก Bean Property ์ค์ ๊ด๋ จ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ ธ์ถํ๋ ThreadPoolExecutor๊ฐ ์๋๋ฐ, ThreadPoolExecutor๊ฐ ์ํ๋ ๋งํผ ์์ ์ ์ด์ง ์๋ค๋ฉด, ConcurrentTaskExecutor๋ฅผ ๋น์ทํ๊ฒ ๊ตฌํํด์ ์ฌ์ฉํ ์๋ ์๋ค. - SimpleThreadPoolTaskExecutor
Quartz SimpleThreadPool์ ํ์ ํด๋์ค๋ก Spring์ Lifecycle callback์ ๋ฐ๋ Executor.
Quartz์ Quartz๊ฐ ์๋ ์ปดํฌ๋ํธ ๊ฐ์ ๊ณต์ ํด์ผ ํ๋ ์ค๋ ๋ ํ์ด ์๋ ๊ฒฝ์ฐ ์ฌ์ฉ. - ThreadPoolTaskExecutor
java.util.concurrent.ThreadPoolExecutor๋ฅผ ๊ตฌ์ฑํ๋ Bean Property๋ฅผ ๋ ธ์ถํ๊ณ TaskExecutor๋ฅผ ์์ํ ๊ตฌํ์ฒด.
ScheduledThreadPoolExecutor์ ๊ตฌํ์ฒด์ด๊ธฐ๋ ํด์ ์ด ์ธํฐํ์ด์ค๊ฐ ํ์ํ๋ค๋ฉด ConcurrentTaskExecutor ๋์ ์ฌ์ฉํ๋ ๊ฑธ ๊ถ์ฅ. - AsyncTaskExecutor
Spring์์ @EnableAsync๋ฅผ ์ฌ์ฉํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉ๋๋ SimpleAsyncTaskExecutor์ ์ถ์ํ ์ธํฐํ์ด์ค. - AsyncListenableTaskExecutor
Submit์ ์ถ๊ฐํ ๋ ListenableFuture ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ธฐ ์ํด ๋ง๋ค์ด์ง ์ธํฐํ์ด์ค.
(ListenableFuture๋ Executor์ Task๋ฅผ ์ ๋ฌํ๊ณ ๋๋ ค ๋ฐ๋ Future ํ์ ์ค ํ๋)
TaskExecutor์ ๊ตฌํ์ฒด๋ ์์์ ๋ดค๋ TaskExecutor์ ์ถ์ํ ์ธํฐํ์ด์ค๋ฅผ ๊ฑฐ์ ๊ทธ๋๋ก ์ฌ์ฉํฉ๋๋ค. ๋ค๋ง ๊ทธ ๊ตฌํ์ฒด์ ๋ฐ๋ผ ๋น๋๊ธฐ์ ์ธ Executor๊ฐ ์๊ณ , ๊ทธ๋ ์ง ์์ Executor๊ฐ ์์ต๋๋ค.
์ ๋ฆฌํ๋ฉด Executor๋ ์ค๋ ๋๋ฅผ ๊ด๋ฆฌํ๋ ์ธํฐํ์ด์ค์ด๋ฉฐ ์ด ๊ด๋ฆฌ์๋ ์ ํด ์ํ ์ ์ด์ ์ค๋ ๋ ์์ฑ ์ ์ด๊ฐ ์์ต๋๋ค.
TaskExecutor์๋ ๋จ์ํ execute ๋ฉ์๋๋ฅผ ํตํด ์คํํ Task๋ง์ ๋ฐ์๋ด๋ฉด ๋๋จธ์ง๋ ์ด๋ฏธ ๊ตฌํ๋์ด ์๋ ๋ฉ์๋๋ค์ ํตํด ์์ ์ ํด ์ํ์ ์ค๋ ๋ ์ ์ด ๋ฑ์ ์งํํด์ค๋๋ค.
๋ง์ฝ, ์ด๋ฌํ ์์ ์ ๋ ์์ธํ๊ฒ ๊ตฌํํ๊ณ ์ ํ๋ค๋ฉด ExecutorService๋ฅผ ์์ํ์ฌ AsyncListenableTaskExecutor์ฒ๋ผ submit ์ ํด๋น ์์ ์ ๋ฐํํ๋๋ก ํ ์๋ ์์ต๋๋ค.
TaskScheduler
TaskExecutor ์ถ์ํ์ ์ถ๊ฐ๋ก Spring 3.0์์๋ ๋ฏธ๋์ ์ด๋ค ์์ ์ ์คํํ ํ์คํฌ(Task)๋ฅผ ์ค์ผ์ค๋งํ ์ง์ ๋ํ ๋ค์ํ ๋ฉ์๋๋ฅผ ๊ฐ์ง TaskScheduler ์ธํฐํ์ด์ค๊ฐ ๋์ ๋์์ต๋๋ค.
Runnable๊ณผ Date๋ง ๋ฐ๋ schedule ๋ฉ์๋๋ฅผ ํตํด ์ง์ ํ ์๊ฐ ํ, ํ์คํฌ๋ฅผ ํ ๋ฒ ์คํํ๋๋ก ํฉ๋๋ค. scheduleFixedRate ๋ฑ์ ํตํด ๋ฐ๋ณตํด์ ํ์คํฌ๋ฅผ ์คํํ ์ ์๋๋ฐ, fixedRate, fixedDelay ๋ชจ๋ ๊ฐ๋จํ ์ฃผ๊ธฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ํ์ง๋ง ์ด๋ณด๋ค ๋ ๋ณต์กํ ์ฃผ๊ธฐ๋ฅผ ์ฌ์ฉํ๊ธฐ๋ฅผ ์ํ๋ค๋ฉด Trigger ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํด ๋ณผ ์ ์์ต๋๋ค.
Trigger
Trigger ์ธํฐํ์ด์ค์ ๊ธฐ๋ณธ์ ๊ณผ๊ฑฐ์ ์คํ ๊ฒฐ๊ณผ๋ ์์์ ์ํฉ์ ๊ธฐ๋ฐ์ ๋ฌ์ ์คํ ์๊ฐ์ ๊ฒฐ์ ํ๋ ์ธํฐํ์ด์ค์ ๋๋ค. ์ด์ ์คํ์ ๊ฒฐ๊ณผ๋ฅผ ๊ณ ๋ คํ๋ ๊ฒฝ์ฐ, ํด๋น ๊ฒฐ๊ณผ ๋ฐ์ดํฐ๋ TriggerContext์ ์์ผ๋ฏ๋ก ์ด๋ฅผ ์ด์ฉํ ์ ์์ต๋๋ค.
์ฝ๋๋ฅผ ์ ์ ์ดํด๋ณด๋ฉด nextExecutionTime ๋ฉ์๋ ๋ถ๋ถ์ TriggerContext๋ฅผ ์ธ์๋ก ๋ฐ๋ ๋ถ๋ถ์ด ์์ต๋๋ค. ์ด Context๋ฅผ ์ด์ฉํด ๊ตฌํ์ฒด์ ์ฐธ๊ณ ํ๋ฉด ๋ฉ๋๋ค.
TriggerContext๋ ์ธํฐํ์ด์ค์ด๋ฉฐ SimpleTriggerContext๋ฅผ ๊ตฌํ์ฒด๋ก ์ฌ์ฉํฉ๋๋ค.
์ฌ๊ธฐ์ ์ค์ํ ๋ถ๋ถ์ ์ด๋ค ๋ฐ์ดํฐ๋ค์ด ๋ชจ๋ ์๋ํ ๋์ด ์์ด ์ํ๋ ๋๋ก ์ด ๋ฐ์ดํฐ๋ค์ ํ์ฅํ์ฌ ํ๋ก๊ทธ๋จ์ ํ๋ฆ์ ๋ฐ๊ฟ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ์์ธํ๊ฑด Trigger ๊ตฌํ์ฒด๋ฅผ ๋ณด๋ฉฐ ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
Trigger ๊ตฌํ์ฒด
Spring Framework์์๋ CronTrigger์ PeriodicTrigger๋ผ๋ ๋ ๊ฐ์ Trigger ๊ตฌํ์ฒด๋ฅผ ์ ๊ณตํฉ๋๋ค.
Cron Trigger๋ cron ํํ์(expression)์ ์ด์ฉํด ํ์คํฌ๋ฅผ ์ค์ผ์ค๋งํ๋ ๋ฐฉ์์ ๋๋ค. ์ฝ๋๋ฅผ ๋ณด๋ฉด ์~๊ธ(์ฃผ์ค)์ 9์์ 5์ ์ฌ์ด ๋งค 15๋ถ๊ฐ ์คํ๋๋ ์ค์ผ์ค๋ง ์ ๋๋ค.
PeriodicTrigger๋ ๊ณ ์ ๋ ์๊ฐ์ ๋ฐ๊ณ ์ ๊ธฐ์ ์ผ๋ก ํ์คํฌ๋ฅผ ์ค์ผ์ค๋งํ๋ ๋ฐฉ์์ ๋๋ค. ์ ์ฝ๋๋ 1ms ๋ง๋ค ํ ๋ฒ์ฉ ํ์คํฌ๋ฅผ ์คํํ๊ฒ ๋ค๋ ์ฝ๋์ ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก TimeUnit์ ๋ ๋ฒ์งธ ์ธ์๋ก ๋ฐ๋๋ฐ, ์ด๋ฅผ ๋ฐ์ง ์์ผ๋ฉด null๋ก ๋ค์ด๊ฐ๋ฉฐ null์ธ ๊ฒฝ์ฐ ๊ธฐ๋ณธ๊ฐ์ธ TimeUnit.MilliSeconds๊ฐ ๋ฉ๋๋ค.
TaskScheduler ๊ตฌํ์ฒด
Spring์ TaskExecutor์ฒ๋ผ TaskScheduler ๋ํ ๊ทธ ๊ตฌํ์ฒด๊ฐ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ํน์ ๊ตฌํ์ฒด์ ์์กดํ๊ฑฐ๋ ๊ตฌํ์ฒด๋ฅผ ํ๋ค๊ฒ ์ง์ ๊ตฌํํด์ผ ํ ํ์๊ฐ ์์ต๋๋ค.
- ConcurrentTaskScheduler
Spring์์ @Scheduled ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉํ๋ ์ค์ผ์ค๋ฌ
๋จ์ผ ์ค๋ ๋๋ง์ผ๋ก๋ก ๋์ - DefaultManagedTaskScheduler
J2EE์ ManagedScheduledExecutorService๋ฅผ ์ฌ์ฉํ ์ค์ผ์ค๋ฌ.
J2SE์ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ ๊ฑฐ์ ๋น์ทํ์ง๋ง ๋งค๋์ง ํํ๋ก ๋์ - ThreadPoolTaskExecutor
Spring์์ @Scheduled ์ด๋ ธํ ์ด์ ์ fixedDelay๋ฅผ ์ด์ฉํด ์ฌ์ฉํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉํ๋ ์ค์ผ์ค๋ฌ
๋ฉํฐ ์ค๋ ๋ ํํ๋ก ๋์. (์ค๋ ๋ ๊ด๋ฆฌ ํํ)
TaskScheduler์ ์ ์ฐ์ฑ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ง์ ์ค๋ ๋๋ฅผ ์์ฑํ์ง ์์์ผ ํ๋ ์๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ํ๊ฒฝ์์ ๋์ํด์ผ ํ๋ ๊ฒฝ์ฐ ์ด๋ฅผ ์ธ๋ถ ์ค๋ ๋ ๊ด๋ฆฌ ํ์ ์์ด ๊ตฌํํด์ฃผ๋ ThreadPoolTaskScheduler ๊ตฌํ์ฒด๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
๋ง์น๋ฉฐ...
์ฌ๊ธฐ๊น์ง ์์ฃผ ๊ฐ๋จํ๊ฒ ์คํ๋ง์์ Bean ๋ด ๋น๋๊ธฐ ์์ ์ฒ๋ฆฌ์ ์ค์ผ์ค๋ง์ ๋ํด ์์๋ดค์ต๋๋ค. ์ด๋ฒ ๊ธ์์ TaskExecutor์ TaskScheduler๋ฅผ ๋์์ ๋ค๋ฃฌ ์ด์ ๋ ์ด๋ค ๋ชจ๋ ์ํธ์์ฉํ๋ ๊ด๊ณ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋ชจ๋ํฐ๋ง์ ์ํด ์ฌ๋ด์์ ์์ฝ๋ ์์ (Scheduled Task)์ด ํ์ํ ๊ฒฝ์ฐ @Scheduled ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ํ์ง๋ง ์ด๋ฅผ ์ง์ ๊ตฌํํ์ฌ ์ฐ๋ฆฌ ์ฌ๋ด ์์คํ ์ ๋ง์ถฐ์ผ ํ๋ค๋ฉด Trigger, TriggerContext ๋ฑ์ ์ถ์ํ ์ธํฐํ์ด์ค๋ก ๊ตฌํํด ๋ณผ ์ ์์ต๋๋ค.
๋ค์ ํฌ์คํธ์์๋ Executor ๊ตฌํ์ฒด๋ค ์ค ๋ช ๊ฐ์ง๋ฅผ ์ด์ฉํด ์ค์ Spring์์ ์ด๋ป๊ฒ ์ฌ์ฉํ ์ ์๋์ง์ ๋ํ ์ค์ ์ ๋ค๋ค๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ฐธ๊ณ : [Spring ๋ ํผ๋ฐ์ค] 26์ฅ ํ์คํฌ(Task) ์คํ๊ณผ ์ค์ผ์ค๋ง
(https://blog.outsider.ne.kr/1066)