Scheduler & Thread Model
๋ฆฌ์กํฐ๋ธ ์คํธ๋ฆผ์ฆ ๋ช ์ธ ์์ฒด๋ ์ค๋ ๋ฉ ๋ชจ๋ธ์ ๊ฐ์ ํ์ง ์์ ํน์ ์ค๋ ๋์์ ์ฝ๋๊ฐ ์คํ๋๋๋ก ๋ณด์ฅํ์ง ์์ผ๋ฉฐ, ์ด๋ ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ด๋ฆฌํด์ผ ํ๋ ์์ญ์ด๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ๋ฆฌ์กํฐ(Reactor)์ ์ฐ์ฐ์ ์ฒด์ธ์ ์ด์ ๋จ๊ณ์ ์ ํธ๋ฅผ ๋ฐ์์ํจ ์ค๋ ๋์ ๋์ผํ ์ค๋ ๋์์ ๊ณ์ ์คํ
์ค์ผ์ค๋ฌ๋ ์ด๋ฌํ ์คํ ํ๋ฆ์ ์๋์ ์ผ๋ก ๋ค๋ฅธ ์ค๋ ๋๋ก ์ ํํ ๋ ์ฌ์ฉ
Spring WebFlux์์๋ Scheduler๋ฅผ ํตํด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ฉฐ, ์คํ ์ปจํ
์คํธ(์ค๋ ๋)๋ฅผ ์์ฝ๊ฒ ์ ํํ๊ณ ์ ์ดํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
ํต์ฌ ์ฐ์ฐ์: publishOn vs subscribeOn
publishOn vs subscribeOnpublishOn๊ณผ subscribeOn๋ ์ค๋ ๋๋ฅผ ์ ํํ๋ ๋ ํต์ฌ ์ฐ์ฐ์์ด๋ค.
subscribeOn(Scheduler)
subscribeOn(Scheduler)๋ฆฌ์กํฐ๋ธ ์คํธ๋ฆผ์ subscribe() ํธ์ถ ์ ๊ตฌ๋
์ ํธ๊ฐ ์ฒด์ธ์ ๊ฐ์ฅ ์๋์์๋ถํฐ ์๋ก(Upstream) ์ ํ๋๋ฉด์ ์์๋๋ค.
์ํฅ ๋ฒ์: ๊ตฌ๋ ์์์ ๊ณผ ๋ฐ์ดํฐ ์์ค๋ฅผ ํฌํจํ ์ ์คํธ๋ฆผ ์ ์ฒด.
publishOn์ผ๋ก ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์ง์ ๋๊ธฐ ์ ๊น์ง ์ํฅ์ฌ์ฉ ํ์: ์ฒด์ธ ๋ด์ ์ฌ๋ฌ ๋ฒ ์ ์ธ๋์ด๋, ์์ค์ ๊ฐ์ฅ ๊ฐ๊น์ด ์ฒซ ๋ฒ์งธ(๋งจ ์์ชฝ)
subscribeOn๋ง ์ ํจ์ฉ๋: ์ฃผ๋ก ๋ธ๋กํน I/O ์์ ์ด๋ ์ค๋ ๊ฑธ๋ฆฌ๋ ์ด๊ธฐํ ์์ ์ ๋ณ๋์ ์ค๋ ๋ ํ์์ ์คํํ์ฌ ๊ธฐ๋ณธ ์ค๋ ๋(์: Netty ์ด๋ฒคํธ ๋ฃจํ)๋ฅผ ์ฐจ๋จํ์ง ์๊ธฐ ์ํด ์ฌ์ฉ
์ด์ฒ๋ผ subscribeOn์ ์ด ๊ตฌ๋
์ ํธ ์ ํ ๋ฐ ์์ค์ ๋ฐ์ดํฐ ๋ฐํ์ ์ด๋ค ์ค๋ ๋์์ ์ํํ ์ง ๊ฒฐ์ ํ๋ค.
publishOn(Scheduler)
publishOn(Scheduler)publishOn์ ์์ ๋ณด๋ค ์๋์ ์๋, ์ฆ ๋ค์ด์คํธ๋ฆผ(Downstream) ์ฐ์ฐ์๋ค์ ์คํ ์ค๋ ๋๋ฅผ ์ง์ ๋ ์ค์ผ์ค๋ฌ์ ์ค๋ ๋๋ก ๋ณ๊ฒฝํ๋ค.
์ํฅ ๋ฒ์:
publishOnํธ์ถ ์ดํ์ ๋ชจ๋ ๋ค์ด์คํธ๋ฆผ ์ฐ์ฐ์์ฌ์ฉ ํ์: ์ฒด์ธ ๋ด์์ ์ฌ๋ฌ ๋ฒ ์ฌ์ฉํ์ฌ ๊ฐ๊ธฐ ๋ค๋ฅธ ์ค๋ ๋ ์ปจํ ์คํธ๋ก ์ ํ ๊ฐ๋ฅ
์ฉ๋: ํน์ ์ฐ์ฐ(์: CPU ์ง์ฝ์ ์์ )์ ๋ณ๋์ ์ค๋ ๋์์ ์ฒ๋ฆฌํ๊ณ ์ถ์ ๋, ํน์ ํน์ ์ค๋ ๋ ์ปจํ ์คํธ๋ก ๋ค์ ๋์์์ผ ํ ๋ ์ฌ์ฉ
์ฐ์ฐ์ ์ฒด์ธ์ ์ค๋ ๋ ๊ฒฝ๊ณ๋ฅผ ๋ง๋๋ ๊ฒ๊ณผ ๊ฐ์ผ๋ฉฐ, publishOn์ ์
์คํธ๋ฆผ(Upstream)์ผ๋ก๋ถํฐ ์ ํธ(onNext, onComplete, onError)๋ฅผ ๋ฐ์, ๋ค์ ์ ํ(emit)ํ๋ค.
ํญ๋ชฉ
subscribeOn()
publishOn()
์ ์ฉ ๋ฒ์
์คํธ๋ฆผ ์ ์ฒด์ ์์ ์ค๋ ๋(Upstream)
์์ ์ดํ์ ์ฐ์ฐ์๋ค(Downstream)์ ์คํ ์ค๋ ๋ ์ง์
์์น ๋ฏผ๊ฐ๋
์์ค ๊ทผ์ฒ ์ฒซ ์ ์ธ๋ง ์ ์ฉ
ํด๋น ์ง์ ์์ ์ค๋ ๋ ๊ฒฝ๊ณ ์์ฑ
์ฃผ์ ์ฉ๋
๋ธ๋กํน ์์ค/์ด๊ธฐํ๋ฅผ ๋ ผ๋ธ๋กํน ํ๊ฒฝ์ผ๋ก ๊ฒฉ๋ฆฌ
์ฐ์ฐ ํน์ฑ์ ๋ฐ๋ผ ์คํ ์ค๋ ๋๋ฅผ ๋ถ๋ฆฌ/์ ํ
์ฝ๋ ์์
์ฃผ์ ์ค์ผ์ค๋ฌ ์ข
๋ฅ
Project Reactor๋ Schedulers ํด๋์ค๋ฅผ ํตํด ๋ฏธ๋ฆฌ ์ ์๋ ์ค์ผ์ค๋ฌ๋ค์ ์ ๊ณตํ๋ค.
Schedulers.parallel(): CPU ์ฝ์ด ์๋งํผ์ ์ค๋ ๋๋ฅผ ๊ฐ์ง ๊ณ ์ ๋ ์ค๋ ๋ ํCPU ์ง์ฝ์ ์ธ ๊ณ์ฐ ์์ ์ ์ต์ ํ
Schedulers.boundedElastic(): ํ์์ ๋ฐ๋ผ ์ค๋ ๋๋ฅผ ๋์ ์ผ๋ก ์์ฑํ๊ณ ์ฌ์ฌ์ฉํ๋ ์ค๋ ๋ ํ์ค๋ ๋ ์์ ์ํ์ ์กด์ฌ
๋ธ๋กํน(Blocking) I/O ์์ ์ ์ฒ๋ฆฌํ ๋ ์ฌ์ฉํ๊ธฐ์ ์ ํฉ
Schedulers.single(): ๋จ ํ๋์ ์ค๋ ๋๋ฅผ ์ฌ์ฌ์ฉํ๋ ์ค์ผ์ค๋ฌ์์๊ฐ ๋ณด์ฅ๋์ด์ผ ํ๋ ์์ ์ฒ๋ฆฌ์ ์ ํฉ
Spring WebFlux์์์ ํ์ฉ
์ผ๋ฐ์ ์ธ WebFlux ์ปจํธ๋กค๋ฌ์์๋ ์ค์ผ์ค๋ฌ๋ฅผ ์ง์ ๋ค๋ฃฐ ์ผ์ด ๊ฑฐ์ ์๋๋ฐ, ์ด๋ฒคํธ ๋ฃจํ ์ค๋ ๋์์ ์ฝ๋๋ฅผ ์คํํ๊ธฐ ๋๋ฌธ์ด๋ค.
ํ์ง๋ง ๋ ๊ฑฐ์ ๋ธ๋กํน(Blocking) ์ฝ๋๋ฅผ WebFlux ํ๊ฒฝ์์ ํธ์ถํด์ผ ํ ๊ฒฝ์ฐ ์ค์ผ์ค๋ฌ ์ฌ์ฉ์ ํ์์ ์ด๋ค. ๋ธ๋กํน ์ฝ๋๊ฐ WebFlux์ ์ด๋ฒคํธ ๋ฃจํ ์ค๋ ๋๋ฅผ ์ ์ ํ๋ ๊ฒ์ ๋ง์์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค.
Schedulers.boundedElastic()๋ฅผ ์ฌ์ฉํ๋ฉด findUserByIdBlocking ๋ฉ์๋๊ฐ ์ด๋ฒคํธ ๋ฃจํ ์ค๋ ๋๋ฅผ ๋ง์ง ์๊ณ , ๋ธ๋กํน I/O ์ ์ฉ ์ค๋ ๋์์ ์์ ํ๊ฒ ์คํ๋๋๋ก ๊ฒฉ๋ฆฌํ ์ ์๋ค.
WebFlux์ ์ค๋ ๋ ๋ชจ๋ธ
Spring WebFlux๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ ์์ ๊ณ ์ ๋ ์ค๋ ๋๋ฅผ ์ฌ์ฉํ์ฌ ์๋ง์ ๋์ ์์ฒญ์ ์ฒ๋ฆฌํ๋ค.
๊ธฐ๋ณธ ์ค๋ ๋: Netty๋ฅผ ๊ธฐ๋ณธ ์๋ฒ๋ก ์ฌ์ฉํ๋ฉฐ, CPU ์ฝ์ด ์์ ๋ง์ถฐ ์์ฑ๋ ์ด๋ฒคํธ ๋ฃจํ(Event Loop) ์ค๋ ๋๋ฅผ ์ฌ์ฉ
๋์ ์์น: ์ด๋ฒคํธ ๋ฃจํ ์ค๋ ๋๋ ์ ๋ ์ฐจ๋จ(block)๋์ง ์์์ผ ํ๋ฉฐ, I/O ์์ ์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ค๋ฅธ ์์ฒญ์ ๊ณ์ ์ฒ๋ฆฌ
๋ง์ฝ ํ๋์ ์ด๋ฒคํธ ๋ฃจํ ์ค๋ ๋๊ฐ
Thread.sleep(), ๋ธ๋กํน DB ํธ์ถ ๋ฑ์ผ๋ก ๋ฉ์ถ๊ฒ ๋๋ฉด, ํด๋น ์ค๋ ๋์ ํ ๋น๋ ๋ชจ๋ ์์ฒญ์ ์ฒ๋ฆฌ๊ฐ ์ง์ฐ๊ฒฐ๊ตญ ์์คํ ์ ์ฒด์ ์ฒ๋ฆฌ๋๊ณผ ์๋ต์ฑ์ ์ฌ๊ฐํ๊ฒ ์ ํ์ํค๋ ์์ธ
์ค๋ ๋ ์ฌ์ฉ ๋ฐฉ์
์ค๋ฌด์์๋ ๋ค์ํ ์ํฉ์ ๋ง์ถฐ Scheduler๋ฅผ ์ ๋ต์ ์ผ๋ก ์ฌ์ฉํด์ผ ํ๋ค.
๋ ผ๋ธ๋กํน ์์ : ๋ณ๋์ ์ค์ผ์ค๋ฌ๋ฅผ ์ง์ ํ ํ์๊ฐ ์์ด, WebFlux์ ๊ธฐ๋ณธ ์ค๋ ๋(์ด๋ฒคํธ ๋ฃจํ)๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉ
๋ธ๋กํน I/O (์: R2DBC๊ฐ ์๋ JDBC, ์ธ๋ถ API ๋๊ธฐ ํธ์ถ)
subscribeOn(Schedulers.boundedElastic())์ ์ฌ์ฉboundedElastic์ค์ผ์ค๋ฌ๋ ๋ธ๋กํน I/O ์์ ์ ์ํด ํน๋ณํ ์ค๊ณํ์์ ๋ฐ๋ผ ์ค๋ ๋๋ฅผ ์์ฑํ์ง๋ง, ๋ฌดํ์ ์์ฑ๋๋ ๊ฒ์ ๋ง๊ธฐ ์ํด ์ํ์ ์ด ์์ผ๋ฉฐ ์ ํด ์ค๋ ๋๋ ์๋์ผ๋ก ์ ๊ฑฐ
์ด๋ฒคํธ ๋ฃจํ ์ค๋ ๋๊ฐ ์๋ ๋ณ๋์ ์ค๋ ๋์์ ๋ธ๋กํน ์์ ์ ์ฒ๋ฆฌํจ์ผ๋ก์จ ์ ์ฒด ์์คํ ์ ๋ฐ์์ฑ ์ ์ง ๊ฐ๋ฅ
CPU ์ง์ฝ์ ์ธ ๊ณ์ฐ ์์
publishOn(Schedulers.parallel())์ฌ์ฉparallel์ค์ผ์ค๋ฌ๋ CPU ์ฝ์ด ์๋งํผ์ ์ค๋ ๋๋ฅผ ๊ฐ์ง ๊ณ ์ ๋ ์ค๋ ๋ ํ ์ ๊ณต๊ณ์ฐ์ด ๋ง์ ์์ ์ ์ด๋ฒคํธ ๋ฃจํ์์ ๋ถ๋ฆฌํ์ฌ ๋ค๋ฅธ ์์ฒญ ์ฒ๋ฆฌ์ ์ํฅ์ ์ฃผ์ง ์๋๋ก ํจ
Last updated
Was this helpful?