๋์๊ด์ ์ฑ ๋์ฌ ๋ฐ ์์ฝ, ๊ด๋ฆฌ ์์คํ ์ ๋๋ค.
- ์ฒดํฌํฌ์ธํธ : https://workflowy.com/s/assessment-check-po/T5YrzcMewfo4J6LW
์ด 5๊ฐ
- https://github.com/Juyounglee95/bookRental
- https://github.com/Juyounglee95/gateway
- https://github.com/Juyounglee95/bookManagement
- https://github.com/Juyounglee95/point
- https://github.com/Juyounglee95/view
- ๊ด๋ฆฌ์๋ ๋์๋ฅผ ๋ฑ๋กํ๋ค.
- ์ฌ์ฉ์๋ ๋์๋ฅผ ์์ฝํ๋ค.
- ๋์๋ฅผ ์์ฝ ์์๋ ํฌ์ธํธ๋ฅผ ์ฌ์ฉํ๋ค. 3-1. ์์ฝ ์ทจ์ ์์๋ ํฌ์ธํธ๊ฐ ๋ฐ๋ฉ๋๋ค.
- ์ฌ์ฉ์๋ ๋์๋ฅผ ๋ฐ๋ฉํ๋ค.
- ํธ๋์ญ์
- ๊ฒฐ์ ๊ฐ ๋์ง ์์ ๊ฒฝ์ฐ ๋์ฌํ ์ ์๋ค. Sync ํธ์ถ
- ์ฅ์ ๊ฒฉ๋ฆฌ
- ๋์๊ด๋ฆฌ ๊ธฐ๋ฅ์ด ์ํ๋์ง ์๋๋ผ๋ ๋์ฌ/์์ฝ์ 365์ผ 24์๊ฐ ๋ฐ์ ์ ์์ด์ผ ํ๋ค Async (event-driven), Eventual Consistency
- ๊ฒฐ์ ์์คํ ์ด ๊ณผ์ค๋๋ฉด ์ฌ์ฉ์๋ฅผ ์ ์๋์ ๋ฐ์ง ์๊ณ ์ ์ํ์ ๊ฒฐ์ ํ๋๋ก ์ ๋ํ๋ค Circuit breaker, fallback
- ์ฑ๋ฅ
- ์ฌ์ฉ์๋ ์ ์ฒด ๋์ ๋ชฉ๋ก์ ํ์ธํ์ฌ ์ ์ฒด ๋์์ ์ํ๋ฅผ ํ์ธํ ์ ์์ด์ผํ๋ค. CQRS
-
๋ถ์ ์ค๊ณ
-
์ด๋ฒคํธ์คํ ๋ฐ:
- ์คํฐ์ปค ์์๋ณ ๊ฐ์ฒด์ ์๋ฏธ๋ฅผ ์ ๋๋ก ์ดํดํ์ฌ ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ์์ ์ฐ๊ณ ์ค๊ณ์ ์ ์ ํ ๋ฐ์ํ๊ณ ์๋๊ฐ?
- ๊ฐ ๋๋ฉ์ธ ์ด๋ฒคํธ๊ฐ ์๋ฏธ์๋ ์์ค์ผ๋ก ์ ์๋์๋๊ฐ?
- ์ด๊ทธ๋ฆฌ๊ฒ์: Command์ Event ๋ค์ ACID ํธ๋์ญ์ ๋จ์์ Aggregate ๋ก ์ ๋๋ก ๋ฌถ์๋๊ฐ?
- ๊ธฐ๋ฅ์ ์๊ตฌ์ฌํญ๊ณผ ๋น๊ธฐ๋ฅ์ ์๊ตฌ์ฌํญ์ ๋๋ฝ ์์ด ๋ฐ์ํ์๋๊ฐ?
-
์๋ธ ๋๋ฉ์ธ, ๋ฐ์ด๋๋ ์ปจํ ์คํธ ๋ถ๋ฆฌ
- ํ๋ณ KPI ์ ๊ด์ฌ์ฌ, ์์ดํ ๋ฐฐํฌ์ฃผ๊ธฐ ๋ฑ์ ๋ฐ๋ฅธ ย Sub-domain ์ด๋ Bounded Context ๋ฅผ ์ ์ ํ ๋ถ๋ฆฌํ์๊ณ ๊ทธ ๋ถ๋ฆฌ ๊ธฐ์ค์ ํฉ๋ฆฌ์ฑ์ด ์ถฉ๋ถํ ์ค๋ช
๋๋๊ฐ?
- ์ ์ด๋ 3๊ฐ ์ด์ ์๋น์ค ๋ถ๋ฆฌ
- ํด๋ฆฌ๊ธ๋ ์ค๊ณ: ๊ฐ ๋ง์ดํฌ๋ก ์๋น์ค๋ค์ ๊ตฌํ ๋ชฉํ์ ๊ธฐ๋ฅ ํน์ฑ์ ๋ฐ๋ฅธ ๊ฐ์์ ๊ธฐ์ Stack ๊ณผ ์ ์ฅ์ ๊ตฌ์กฐ๋ฅผ ๋ค์ํ๊ฒ ์ฑํํ์ฌ ์ค๊ณํ์๋๊ฐ?
- ์๋น์ค ์๋๋ฆฌ์ค ์ค ACID ํธ๋์ญ์ ์ด ํฌ๋ฆฌํฐ์ปฌํ Use ์ผ์ด์ค์ ๋ํ์ฌ ๋ฌด๋ฆฌํ๊ฒ ์๋น์ค๊ฐ ๊ณผ๋คํ๊ฒ ์กฐ๋ฐํ ๋ถ๋ฆฌ๋์ง ์์๋๊ฐ?
- ํ๋ณ KPI ์ ๊ด์ฌ์ฌ, ์์ดํ ๋ฐฐํฌ์ฃผ๊ธฐ ๋ฑ์ ๋ฐ๋ฅธ ย Sub-domain ์ด๋ Bounded Context ๋ฅผ ์ ์ ํ ๋ถ๋ฆฌํ์๊ณ ๊ทธ ๋ถ๋ฆฌ ๊ธฐ์ค์ ํฉ๋ฆฌ์ฑ์ด ์ถฉ๋ถํ ์ค๋ช
๋๋๊ฐ?
-
์ปจํ ์คํธ ๋งคํ / ์ด๋ฒคํธ ๋๋ฆฌ๋ธ ์ํคํ ์ฒ
- ์ ๋ฌด ์ค์์ฑ๊ณผย ๋๋ฉ์ธ๊ฐ ์์ด์ ๊ตฌ๋ถํ ์ ์๋๊ฐ? (Core, Supporting, General Domain)
- Request-Response ๋ฐฉ์๊ณผ ์ด๋ฒคํธ ๋๋ฆฌ๋ธ ๋ฐฉ์์ ๊ตฌ๋ถํ์ฌ ์ค๊ณํ ์ ์๋๊ฐ?
- ์ฅ์ ๊ฒฉ๋ฆฌ: ์ํฌํ ์๋น์ค๋ฅผ ์ ๊ฑฐ ํ์ฌ๋ ๊ธฐ์กด ์๋น์ค์ ์ํฅ์ด ์๋๋ก ์ค๊ณํ์๋๊ฐ?
- ์ ๊ท ์๋น์ค๋ฅผ ์ถ๊ฐ ํ์์๋ ๊ธฐ์กด ์๋น์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํฅ์ด ์๋๋ก ์ค๊ณ(์ด๋ ค์๋ ์ํคํ์ฒ)ํ ์ ์๋๊ฐ?
- ์ด๋ฒคํธ์ ํด๋ฆฌ์๋ฅผ ์ฐ๊ฒฐํ๊ธฐ ์ํ Correlation-key ์ฐ๊ฒฐ์ ์ ๋๋ก ์ค๊ณํ์๋๊ฐ?
-
ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ
- ์ค๊ณ ๊ฒฐ๊ณผ์ ๋ฐ๋ฅธ ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ ๋ค์ด์ด๊ทธ๋จ์ ์ ๋๋ก ๊ทธ๋ ธ๋๊ฐ?
-
-
๊ตฌํ
-
[DDD] ๋ถ์๋จ๊ณ์์์ ์คํฐ์ปค๋ณ ์์๊ณผ ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ์ ๋ฐ๋ผ ๊ตฌํ์ฒด๊ฐ ๋งคํ๋๊ฒ ๊ฐ๋ฐ๋์๋๊ฐ?
- Entity Pattern ๊ณผ Repository Pattern ์ ์ ์ฉํ์ฌ JPA ๋ฅผ ํตํ์ฌ ๋ฐ์ดํฐ ์ ๊ทผ ์ด๋ํฐ๋ฅผ ๊ฐ๋ฐํ์๋๊ฐ
- [ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ] REST Inbound adaptor ์ด์ธ์ gRPC ๋ฑ์ Inbound Adaptor ๋ฅผ ์ถ๊ฐํจ์ ์์ด์ ๋๋ฉ์ธ ๋ชจ๋ธ์ ์์์ ์ฃผ์ง ์๊ณ ์๋ก์ด ํ๋กํ ์ฝ์ ๊ธฐ์กด ๊ตฌํ์ฒด๋ฅผ ์ ์์ํฌ ์ ์๋๊ฐ?
- ๋ถ์๋จ๊ณ์์์ ์ ๋น์ฟผํฐ์ค ๋ญ๊ท์ง (์ ๋ฌดํ์ฅ์์ ์ฐ๋ ์ฉ์ด) ๋ฅผ ์ฌ์ฉํ์ฌ ์์ค์ฝ๋๊ฐ ์์ ๋์๋๊ฐ?
-
Request-Response ๋ฐฉ์์ ์๋น์ค ์ค์ฌ ์ํคํ ์ฒ ๊ตฌํ
- ๋ง์ดํฌ๋ก ์๋น์ค๊ฐ Request-Response ํธ์ถ์ ์์ด ๋์ ์๋น์ค๋ฅผ ์ด๋ ํ ๋ฐฉ์์ผ๋ก ์ฐพ์์ ํธ์ถ ํ์๋๊ฐ? (Service Discovery, REST, FeignClient)
- ์ํท๋ธ๋ ์ด์ปค๋ฅผ ํตํ์ฌย ์ฅ์ ๋ฅผ ๊ฒฉ๋ฆฌ์ํฌ ์ ์๋๊ฐ?
-
์ด๋ฒคํธ ๋๋ฆฌ๋ธ ์ํคํ ์ฒ์ ๊ตฌํ
- ์นดํ์นด๋ฅผ ์ด์ฉํ์ฌ PubSub ์ผ๋ก ํ๋ ์ด์์ ์๋น์ค๊ฐ ์ฐ๋๋์๋๊ฐ?
- Correlation-key: ๊ฐ ์ด๋ฒคํธ ๊ฑด (๋ฉ์์ง)๊ฐ ์ด๋ ํ ํด๋ฆฌ์๋ฅผ ์ฒ๋ฆฌํ ๋ ์ด๋ค ๊ฑด์ ์ฐ๊ฒฐ๋ ์ฒ๋ฆฌ๊ฑด์ธ์ง๋ฅผ ๊ตฌ๋ณํ๊ธฐ ์ํ Correlation-key ์ฐ๊ฒฐ์ ์ ๋๋ก ๊ตฌํ ํ์๋๊ฐ?
- Message Consumer ๋ง์ดํฌ๋ก์๋น์ค๊ฐ ์ฅ์ ์ํฉ์์ ์์ ๋ฐ์ง ๋ชปํ๋ ๊ธฐ์กด ์ด๋ฒคํธ๋ค์ ๋ค์ ์์ ๋ฐ์ ์ฒ๋ฆฌํ๋๊ฐ?
- Scaling-out: Message Consumer ๋ง์ดํฌ๋ก์๋น์ค์ Replica ๋ฅผ ์ถ๊ฐํ์๋ ์ค๋ณต์์ด ์ด๋ฒคํธ๋ฅผ ์์ ํ ์ ์๋๊ฐ
- CQRS: Materialized View ๋ฅผ ๊ตฌํํ์ฌ, ํ ๋ง์ดํฌ๋ก์๋น์ค์ ๋ฐ์ดํฐ ์๋ณธ์ ์ ๊ทผ์์ด(Composite ์๋น์ค๋ ์กฐ์ธSQL ๋ฑ ์์ด) ๋ ๋ด ์๋น์ค์ ํ๋ฉด ๊ตฌ์ฑ๊ณผ ์ฆ์ ์กฐํ๊ฐ ๊ฐ๋ฅํ๊ฐ?
-
ํด๋ฆฌ๊ธ๋ ํ๋ก๊ทธ๋๋ฐ
- ๊ฐ ๋ง์ดํฌ๋ก ์๋น์ค๋ค์ด ํ๋์ด์์ ๊ฐ์์ ๊ธฐ์ Stack ์ผ๋ก ๊ตฌ์ฑ๋์๋๊ฐ?
- ๊ฐ ๋ง์ดํฌ๋ก ์๋น์ค๋ค์ด ๊ฐ์์ ์ ์ฅ์ ๊ตฌ์กฐ๋ฅผ ์์จ์ ์ผ๋ก ์ฑํํ๊ณ ๊ฐ์์ ์ ์ฅ์ ์ ํ (RDB, NoSQL, File System ๋ฑ)์ ์ ํํ์ฌ ๊ตฌํํ์๋๊ฐ?
-
API ๊ฒ์ดํธ์จ์ด
- API GW๋ฅผ ํตํ์ฌ ๋ง์ดํฌ๋ก ์๋น์ค๋ค์ ์ง์ ์ ์ ํต์ผํ ์ ์๋๊ฐ?
- ๊ฒ์ดํธ์จ์ด์ ์ธ์ฆ์๋ฒ(OAuth), JWT ํ ํฐ ์ธ์ฆ์ ํตํ์ฌ ๋ง์ดํฌ๋ก์๋น์ค๋ค์ ๋ณดํธํ ์ ์๋๊ฐ?
-
-
์ด์
- SLA ์ค์
- ์ ํํ๋ง: Liveness Probe ๋ฅผ ํตํ์ฌ ์ด๋ ํ ์๋น์ค์ health ์ํ๊ฐ ์ง์์ ์ผ๋ก ์ ํ๋จ์ ๋ฐ๋ผ ์ด๋ ํ ์๊ณ์น์์ pod ๊ฐ ์ฌ์๋๋ ๊ฒ์ ์ฆ๋ช ํ ์ ์๋๊ฐ?
- ์ํท๋ธ๋ ์ด์ปค, ๋ ์ดํธ๋ฆฌ๋ฐ ๋ฑ์ ํตํ ์ฅ์ ๊ฒฉ๋ฆฌ์ ์ฑ๋ฅํจ์จ์ ๋ํ ์ ์๋๊ฐ?
- ์คํ ์ค์ผ์ผ๋ฌ (HPA) ๋ฅผ ์ค์ ํ์ฌ ํ์ฅ์ ์ด์์ด ๊ฐ๋ฅํ๊ฐ?
- ๋ชจ๋ํฐ๋ง, ์จ๋ฟํ :
- ๋ฌด์ ์ง ์ด์ CI/CD (10)
- Readiness Probe ์ ์ค์ ๊ณผ Rolling update์ ํตํ์ฌ ์ ๊ท ๋ฒ์ ์ด ์์ ํ ์๋น์ค๋ฅผ ๋ฐ์ ์ ์๋ ์ํ์ผ๋ ์ ๊ท๋ฒ์ ์ ์๋น์ค๋ก ์ ํ๋จ์ siege ๋ฑ์ผ๋ก ์ฆ๋ช
- Contract Test : ์๋ํ๋ ๊ฒฝ๊ณ ํ ์คํธ๋ฅผ ํตํ์ฌ ๊ตฌํ ์ค๋ฅ๋ API ๊ณ์ฝ์๋ฐ๋ฅผ ๋ฏธ๋ฆฌ ์ฐจ๋จ ๊ฐ๋ฅํ๊ฐ?
- SLA ์ค์
- ์ด๋ฒคํธ์คํ ๋ฐ ๊ฒฐ๊ณผ: http://msaez.io/#/storming/nZJ2QhwVc4NlVJPbtTkZ8x9jclF2/every/a77281d704710b0c2e6a823b6e6d973a/-M5AV2z--su_i4BfQfeF
- ๋๋ฉ์ธ ์์ด ๋ถ๋ฆฌ
- Core Domain: bookRental, bookManagement : ํต์ฌ ์๋น์ค
- Supporting Domain: marketing, customer : ๊ฒฝ์๋ ฅ์ ๋ด๊ธฐ์ํ ์๋น์ค
- General Domain: point : ๊ฒฐ์ ์๋น์ค๋ก 3rd Party ์ธ๋ถ ์๋น์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฒฝ์๋ ฅ์ด ๋์ (ํํฌ์์ผ๋ก ์ดํ ์ ํํ ์์ )
- View Model ์ถ๊ฐ
<๊ธฐ๋ฅ์ ์๊ตฌ์ฌํญ ๊ฒ์ฆ>
- ๊ด๋ฆฌ์๋ ๋์๋ฅผ ๋ฑ๋กํ๋ค. ok
- ์ฌ์ฉ์๋ ๋์๋ฅผ ์์ฝํ๋ค. ok
- ๋์๋ฅผ ์์ฝ ์์๋ ํฌ์ธํธ๋ฅผ ์ฌ์ฉํ๋ค. ok
- ์์ฝ ์ทจ์ ์์๋ ํฌ์ธํธ๊ฐ ๋ฐ๋ฉ๋๋ค. ok
- ์ฌ์ฉ์๋ ๋์๋ฅผ ๋ฐ๋ฉํ๋ค. ok
- ์ฌ์ฉ์๋ ์์ฝ์ ์ทจ์ํ ์ ์๋ค (ok)
- ์์ฝ์ด ์ทจ์๋๋ฉด ํฌ์ธํธ๊ฐ ๋ฐ๋ฉ๋๊ณ , ๋์์ ์ํ๊ฐ ์์ฝ ์ทจ์๋ก ๋ณ๊ฒฝ๋๋ค (ok)
- ์ฌ์ฉ์๋ ๋์์ํ๋ฅผ ์ค๊ฐ์ค๊ฐ ์กฐํํ๋ค (View-green sticker ์ ์ถ๊ฐ๋ก ok)
- ๋์๊ฐ ๋ฑ๋ก/์์ฝ/์์ฝ์ทจ์/๋ฐ๋ฉ ์, ๋์์ ์ํ๊ฐ ๋ณ๊ฒฝ๋์ด ์ ์ฒด ๋์ ๋ฆฌ์คํธ์ ๋ฐ์๋๋ค. ์ฌ์ฉ์์ ๊ด๋ฆฌ์ ๋ชจ๋ ์ด๋ฅผ ํ์ธํ ์ ์๋ค. ok
- ๋ง์ดํฌ๋ก ์๋น์ค๋ฅผ ๋๋๋๋ ์๋๋ฆฌ์ค์ ๋ํ ํธ๋์ญ์
์ฒ๋ฆฌ
- ๋์ ์์ฝ์ ๊ฒฐ์ ์ฒ๋ฆฌ: ์์ฝ์๋ฃ์ ํฌ์ธํธ ๊ฒฐ์ ์ฒ๋ฆฌ์ ๋ํด์๋ Request-Response ๋ฐฉ์ ์ฒ๋ฆฌ
- ๊ฒฐ์ ์๋ฃ์ ๋์ ์ํ ๋ณ๊ฒฝ: Eventual Consistency ๋ฐฉ์์ผ๋ก ํธ๋์ญ์ ์ฒ๋ฆฌํจ.
- ๋๋จธ์ง ๋ชจ๋ inter-microservice ํธ๋์ญ์ : ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ ์์ ์ด ํฌ๋ฆฌํฐ์ปฌํ์ง ์์ ๋ชจ๋ ๊ฒฝ์ฐ๊ฐ ๋๋ถ๋ถ์ด๋ผ ํ๋จ, Eventual Consistency ๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ฑํํจ.
- Chris Richardson, MSA Patterns ์ฐธ๊ณ ํ์ฌ Inbound adaptor์ Outbound adaptor๋ฅผ ๊ตฌ๋ถํจ
- ํธ์ถ๊ด๊ณ์์ PubSub ๊ณผ Req/Resp ๋ฅผ ๊ตฌ๋ถํจ
- ์๋ธ ๋๋ฉ์ธ๊ณผ ๋ฐ์ด๋๋ ์ปจํ ์คํธ์ ๋ถ๋ฆฌ: ๊ฐ ํ์ KPI ๋ณ๋ก ์๋์ ๊ฐ์ด ๊ด์ฌ ๊ตฌํ ์คํ ๋ฆฌ๋ฅผ ๋๋ ๊ฐ์ง
๋ถ์/์ค๊ณ ๋จ๊ณ์์ ๋์ถ๋ ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ์ ๋ฐ๋ผ, ๊ฐ BC๋ณ๋ก ๋๋ณ๋๋ ๋ง์ดํฌ๋ก ์๋น์ค๋ค์ ์คํ๋ง๋ถํธ๋ก ๊ตฌํํจ. ๊ตฌํํ ๊ฐ ์๋น์ค๋ฅผ ๋ก์ปฌ์์ ์คํํ๋ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ๋ค (๊ฐ์์ ํฌํธ๋๋ฒ๋ 8081 ~ 808n ์ด๋ค) bookManagement/ bookRental/ gateway/ point/ view/
cd bookManagement
mvn spring-boot:run
cd bookRental
mvn spring-boot:run
cd gateway
mvn spring-boot:run
cd point
mvn spring-boot:run
cd view
mvn spring-boot:run
- ๊ฐ ์๋น์ค๋ด์ ๋์ถ๋ ํต์ฌ Aggregate Root ๊ฐ์ฒด๋ฅผ Entity ๋ก ์ ์ธ. ์ด๋ ๊ฐ๋ฅํ ํ์ ์์ ์ฌ์ฉํ๋ ์ธ์ด (์ ๋น์ฟผํฐ์ค ๋ญ๊ท์ง)๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํจ.
package library;
import javax.persistence.*;
import org.springframework.beans.BeanUtils;
import java.util.List;
@Entity
@Table(name="PointSystem_table")
public class PointSystem {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private Long bookId;
private Long pointQty =(long)100;
@PostPersist
public void onPostPersist(){
PointUsed pointUsed = new PointUsed(this);
BeanUtils.copyProperties(this, pointUsed);
pointUsed.publish();
}
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPointQty() {
return pointQty;
}
public void setPointQty(Long pointQty) {
this.pointQty = pointQty;
}
}
- Entity Pattern ๊ณผ Repository Pattern ์ ์ ์ฉํ์ฌ JPA ๋ฅผ ํตํ์ฌ ๋ค์ํ ๋ฐ์ดํฐ์์ค ์ ํ (RDB or NoSQL) ์ ๋ํ ๋ณ๋์ ์ฒ๋ฆฌ๊ฐ ์๋๋ก ๋ฐ์ดํฐ ์ ๊ทผ ์ด๋ํฐ๋ฅผ ์๋ ์์ฑํ๊ธฐ ์ํ์ฌ Spring Data REST ์ RestRepository ๋ฅผ ์ ์ฉํ์๋ค
package library;
import org.springframework.data.repository.PagingAndSortingRepository;
public interface PointSystemRepository extends PagingAndSortingRepository<PointSystem, Long>{
}
- ์ ์ฉ ํ REST API ์ ํ ์คํธ
# bookManagement ์๋น์ค์ ๋์ ๋ฑ๋ก์ฒ๋ฆฌ
http POST http://52.231.116.117:8080/bookManageSystems bookName="JPA"
# bookRental ์๋น์ค์ ์์ฝ์ฒ๋ฆฌ
http POST http://52.231.116.117:8080/bookRentalSystems/returned/1
# bookRental ์๋น์ค์ ๋ฐ๋ฉ์ฒ๋ฆฌ
http POST http://52.231.116.117:8080/bookRentalSystems/reserve/1
# bookRental ์๋น์ค์ ์์ฝ์ทจ์์ฒ๋ฆฌ
http POST http://52.231.116.117:8080/bookRentalSystems/reserveCanceled/1
# ๋์ ์ํ ํ์ธ
http://52.231.116.117:8080/bookLists
๋ถ์๋จ๊ณ์์์ ์กฐ๊ฑด ์ค ํ๋๋ก ์์ฝ(bookRental)->๊ฒฐ์ (point) ๊ฐ์ ํธ์ถ์ ๋๊ธฐ์ ์ผ๊ด์ฑ์ ์ ์งํ๋ ํธ๋์ญ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ๋ก ํ์๋ค. ํธ์ถ ํ๋กํ ์ฝ์ ์ด๋ฏธ ์์ Rest Repository ์ ์ํด ๋ ธ์ถ๋์ด์๋ REST ์๋น์ค๋ฅผ FeignClient ๋ฅผ ์ด์ฉํ์ฌ ํธ์ถํ๋๋ก ํ๋ค.
- ๊ฒฐ์ ์๋น์ค๋ฅผ ํธ์ถํ๊ธฐ ์ํ์ฌ Stub๊ณผ (FeignClient) ๋ฅผ ์ด์ฉํ์ฌ Service ๋ํ ์ธํฐํ์ด์ค (Proxy) ๋ฅผ ๊ตฌํ
# (app) pointSystemService.java
@FeignClient(name="point", url="http://52.231.116.117:8080")
public interface PointSystemService {
@RequestMapping(method= RequestMethod.POST, path="/pointSystems", consumes = "application/json")
public void usePoints(@RequestBody PointSystem pointSystem);
}
- ์์ฝ์ ๋ฐ์ ์งํ(@PostPersist) ๊ฒฐ์ ๋ฅผ ์์ฒญํ๋๋ก ์ฒ๋ฆฌ -> BookRental์ ์์ฑ์ BookManageSystem์์ ๋์๋ฅผ ๋ฑ๋กํ ์งํ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์, Post์์ฒญ์ผ๋ก ์์ฝ์ด ๋ค์ด์จ ํ ๊ฒฐ์ ์์ฒญํ๋๋ก ์ฒ๋ฆฌํจ.
# BookRentalSystemController.java (Entity)
@PostMapping("/bookRentalSystems/reserve/{id}")
public void bookReserve(@PathVariable(value="id")Long id){
PointSystem pointSystem = new PointSystem();
pointSystem.setBookId(id);
PointSystemService pointSystemService = Application.applicationContext.
getBean(library.external.PointSystemService.class);
pointSystemService.usePoints(pointSystem);
}
}
๊ฒฐ์ ๊ฐ ์ด๋ฃจ์ด์ง ํ์ ๋์๋์ฌ์์คํ ์ผ๋ก ์ด๋ฅผ ์๋ ค์ฃผ๋ ํ์๋ ๋๊ธฐ์์ด ์๋๋ผ ๋น ๋๊ธฐ์์ผ๋ก ์ฒ๋ฆฌํ์ฌ ๋์๋์ฌ์์คํ ์ ์ฒ๋ฆฌ๋ฅผ ์ํ์ฌ ๋์ ์ํ ์ ๋ฐ์ดํธ๋ ๋ธ๋กํน ๋์ง ์๋๋ก ์ฒ๋ฆฌํ๋ค.
- ์ด๋ฅผ ์ํ์ฌ ๊ฒฐ์ ์ด๋ ฅ์ ๊ธฐ๋ก์ ๋จ๊ธด ํ์ ๊ณง๋ฐ๋ก ๊ฒฐ์ ์น์ธ์ด ๋์๋ค๋ ๋๋ฉ์ธ ์ด๋ฒคํธ๋ฅผ ์นดํ์นด๋ก ์ก์ถํ๋ค(Publish)
#PointSystem.Java (Entity)
{
@PostPersist
public void onPostPersist(){
PointUsed pointUsed = new PointUsed(this);
BeanUtils.copyProperties(this, pointUsed);
pointUsed.publish();
}
}
๊ฒฐ์ ์๋ฃ ์ด๋ฒคํธ๋ฅผ ๋์๋์ฌ์์คํ ์ ๋ฆฌ์ค๋๊ฐ ๋ฐ์, ๋์์ ์ํ๋ฅผ ์์ฝ์๋ฃ๋ก ๋ณ๊ฒฝํ๋ค.
(BookRentalSystem) PolicyHandler.JAVA
{
@StreamListener(KafkaProcessor.INPUT) //ํฌ์ธํธ ๊ฒฐ์ ์๋ฃ์
public void wheneverPointUsed_ChangeStatus(@Payload PointUsed pointUsed){
try {
if (pointUsed.isMe()) {
System.out.println("##### point use completed : " + pointUsed.toJson());
BookRentalSystem bookRentalSystem = bookRentalSystemRepository.findById(pointUsed.getBookId()).get();
bookRentalSystem.setBookStatus("Reserved Complete");
bookRentalSystemRepository.save(bookRentalSystem);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
๋์์ํ๊ฐ ๋ณ๊ฒฝ๋๋ฉด, Reserved๋ผ๋ ์ด๋ฒคํธ๋ฅผ ๋ฐํํ๋ค.
BookRentalSystem.java (Entity)
{
@PostUpdate
public void bookStatusUpdate(){
if(this.getBookStatus().equals("Returned")){
Returned returned = new Returned(this);
BeanUtils.copyProperties(this, returned);
returned.publish();
}else if(this.getBookStatus().equals("Canceled")){
ReservationCanceled reservationCanceled = new ReservationCanceled(this);
BeanUtils.copyProperties(this, reservationCanceled);
reservationCanceled.publish();
}else if(this.getBookStatus().equals("Reserved Complete")){
Reserved reserved = new Reserved(this);
BeanUtils.copyProperties(this, reserved);
reserved.publish();
}
}
}
๊ฒฐ๊ณผ : ํฌ์ธํธ๊ฐ ์ฌ์ฉ๋ ํ์, ์์ฝ์ด ์๋ฃ๋๋ ๊ฒ๊ณผ ๋์์ ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๊ฒ์ BookListViewํ์ธ ํ ์ ์๋ค.
๊ฐ ๊ตฌํ์ฒด๋ค์ ๊ฐ์์ source repository ์ ๊ตฌ์ฑ๋์๊ณ , ์ฌ์ฉํ CI/CD ํ๋ซํผ์ azure๋ฅผ ์ฌ์ฉํ์์ผ๋ฉฐ, pipeline build script ๋ ๊ฐ ํ๋ก์ ํธ ํด๋ ์ดํ์ azure-pipeline.yml ์ ํฌํจ๋์๋ค.
์๋ ์ด๋ฏธ์ง๋ azure์ pipeline์ ๊ฐ๊ฐ์ ์๋น์ค๋ค์ ์ฌ๋ ค, ์ฝ๋๊ฐ ์ ๋ฐ์ดํธ ๋ ๋๋ง๋ค ์๋์ผ๋ก ๋น๋/๋ฐฐํฌ ํ๋๋ก ํ์๋ค.
๊ทธ ๊ฒฐ๊ณผ kubernetes cluster์ ์๋์ ๊ฐ์ด ์๋น์ค๊ฐ ์ฌ๋ผ๊ฐ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋ํ, ๊ธฐ๋ฅ๋ค๋ ์ ์์ ์ผ๋ก ์๋ํจ์ ์ ์ ์๋ค.
<์ด๋ฒคํธ ๋ ๋ฆฌ๊ธฐ>
<๋์ ๊ฒฐ๊ณผ>
- ํฌ์ธํธ์๋น์ค์ ๋ํ replica ๋ฅผ ๋์ ์ผ๋ก ๋๋ ค์ฃผ๋๋ก HPA ๋ฅผ ์ค์ ํ๋ค. ์ค์ ์ CPU ์ฌ์ฉ๋์ด 15ํ๋ก๋ฅผ ๋์ด์๋ฉด replica ๋ฅผ 10๊ฐ๊น์ง ๋๋ ค์ค๋ค:
- ์คํ ์ค์ผ์ผ์ด ์ด๋ป๊ฒ ๋๊ณ ์๋์ง ๋ชจ๋ํฐ๋ง์ ๊ฑธ์ด๋๋ค:
- ์ํฌ๋ก๋๋ฅผ 2๋ถ ๋์ ๊ฑธ์ด์ค ํ ํ ์คํธ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
Autoscaler์ค์ ๊ณผ Readiness ์ ๊ฑฐ๋ฅผ ํ๋ค, ๋ถํ๋ฅผ ๋ฃ์๋ค.
์ดํ Readiness๋ฅผ ์ ๊ฑฐํ ์ฝ๋๋ฅผ ์ ๋ฐ์ดํธํ์ฌ ์ ๋ฒ์ ์ผ๋ก ๋ฐฐํฌ๋ฅผ ์์ํ๋ค.
๊ทธ ๊ฒฐ๊ณผ๋ ์๋๋ ๊ฐ๋ค.
๋ค์ Readiness ์ค์ ์ ๋ฃ๊ณ ๋ถํ๋ฅผ ๋ฃ์๋ค.
๊ทธ๋ฆฌ๊ณ ์๋ฒ์ ์ผ๋ก ๋ฐฐํฌํ ๋ค ๊ทธ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
๋ฐฐํฌ๊ธฐ๊ฐ ๋์ Availability ๊ฐ ๋ณํ์๊ธฐ ๋๋ฌธ์ ๋ฌด์ ์ง ์ฌ๋ฐฐํฌ๊ฐ ์ฑ๊ณตํ ๊ฒ์ผ๋ก ํ์ธ๋จ.