๐Ÿน ์˜ˆ์น˜๊ธˆ ์ฐจ์•ก ๋น„๊ต Spring Batch ๋ฆฌํŽ™ํ† ๋ง

์ž‘์—… ๋ชฉ์ 

๊ธฐ์กด ์˜ˆ์น˜๊ธˆ ์ฐจ์•ก๋น„๊ต Batch์˜ Tasklet๋ฐฉ์‹์˜ ๋ฐฐ์น˜์˜ ๋‹จ์ ์„ ๋ณด์™„ํ•˜๋Š” chunk ๋ฐฉ์‹์˜ ๋ฐฐ์น˜๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , ๋‚˜์•„๊ฐ€ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์˜ Batch์—๋„ ํšจ๊ณผ์ ์œผ๋กœ ๋น ๋ฅด๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์žฌ์‚ฌ์šฉ์„ฑ/์œ ์ง€๋ณด์ˆ˜์„ฑ ๋†’์€ ์ฝ”๋“œ, ์„ ๋ก€๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•จ์ด๋‹ค.


์ž‘์—… ๊ณ„ํš

  1. Chunk, Partioning๋ฐฉ์‹์„ Job์„ ์ถ”๊ฐ€ ๊ฐœ๋ฐœ (๊ธฐ์กด balanceJob ์œ ์ง€)
  2. ๋‹น๋ถ„๊ฐ„ ๋‘ Job์„ ๋ณ‘ํ–‰ํ•˜๋ฉด์„œ ๋น„๊ต
  3. ์ถ”๊ฐ€ํ•œ Job ๊ธฐ๋Šฅ์— ๋ฌธ์ œ์—†๋‹ค๋ฉด ๊ธฐ์กด balanceJob ์‚ญ์ œ

+ ํ”Œ๋กœ์šฐ ์ฐจํŠธ

ํšŒ์‚ฌ ์€ํ–‰ ์„œ๋น„์Šค1111.png Spring Batch Tasklet ์˜ˆ์น˜๊ธˆ ์ž”์•ก ๋น„๊ต 1.png Spring Batch Tasklet ์˜ˆ์น˜๊ธˆ ์ž”์•ก ๋น„๊ต ์ž˜๋ชป๋œ ์ฐจ์•ก๋ฐœ์ƒ ์ธ์‹ ํƒ€์ž„๋ผ์ธ.png


๋ฌธ์ œ์  ๋ถ„์„


1. ํ•˜๋‚˜์˜ ํŠธ๋ Œ์ ์…˜์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ, ์‹คํŒจ์‹œ ์ฒ˜์Œ๋ถ€ํ„ฐ ์žฌ์‹œ๋„ ํ•ด์•ผํ•จ

  • ์ฒ˜์Œ ๊ฐ€์ ธ์˜จ Point ๋ฐฐ์น˜ ์™„๋ฃŒ์‹œ ๊นŒ์ง€ ๊ณ„์† ๋ฌผ๊ณ ์žˆ๋‹ค. -> ํ•œ ํŠธ๋ Œ์ ์…˜์˜ ๋ฒ”์œ„๊ฐ€ ๋„“๋‹ค.

2. ํ•œ ํŠธ๋ Œ์ ์…˜๋‚ด์—์„œ ๊ธด ์‹œ๊ฐ„์„ ๋™์ž‘ํ•˜์—ฌ, ๋ฐฐ์น˜์ค‘ ์ผ์–ด๋‚˜๋Š” insert/update(์˜ˆ์น˜๊ธˆ ์ž…๊ธˆ ์ถœ๊ธˆ) ๊ฑด์„ ๊ฐ์ง€ํ•˜์ง€ ๋ชปํ•จ

์ •๋ณด
  • ๋ณ‘๋ชฉ์ด ์žˆ์ง„ ์•Š์œผ๋‚˜, ํ•œ ๋ฐฐ์น˜์„œ๋น„์Šค์˜ ํŠธ๋ Œ์ ์…˜์—์„œ ์™ธ๋ถ€ api์˜ ๊ฐ’ ๋ณ€๋™์„ ๋ฐ˜์˜ํ•˜์ง€ ๋ชปํ•จ.

๋ฐฐ์น˜ ๋™์ž‘ ๋กœ์ง


7:00 -> ํšŒ์› ๊ฐœ๊ฐœ์ธ ๋ณ„ ๋น„๊ต. ๋ฌธ์ž๋Š” 9์‹œ 30๋ถ„์— ์˜ˆ์•ฝ๋ฌธ์ž๋กœ ์˜ค์ง€๋งŒ, ์‹ค์ œ ๋กœ์ง์€ 7์‹œ์— ๋ˆ๋‹ค

  • G5-Point ๋“ฑ์€ ์ฒ˜์Œ 7์‹œ ์‹œ์ ์— ๋ฌถ์—ฌ์žˆ๋‹ค. ํšŒ์›๋ณ„๋กœ ์‹ค๋ฐ์ดํ„ฐ๋ฅผ ๊ฑด๊ฑด์ด api(์‹ ํ•œ)๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋น„๊ตํ•œ๋‹ค. ๋•Œ๋ฌธ์—, 7์‹œ ์ดํ›„์— ์ˆ˜์ •๋œ๋ฐ์ดํ„ฐ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ˜์˜ํ•˜์ง€ ๋ชปํ•œ๋‹ค.

์‹ ํ•œAPI๊ฐ€ main๋ฐ์ดํ„ฐ.



New Batch์˜ ์ฃผ์š” ๊ธฐ์ˆ  ๋ฐ ๋ชฉ์ 


Partitioning

  • ๋ชฉ์  : batch์˜ step ๋ ˆ๋ฒจ์—์„œ์˜ ์Šค๋ ˆ๋“œ ๋ถ„๋ฆฌ ( ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ )
ํ”„๋กœ์„ธ์Šค(์„œ๋น„์Šค ๋กœ์ง)๋‹จ๊ณ„์—์„œ ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๊ฒƒ๊ณผ ์–ด๋– ํ•œ์ฐจ์ด๊ฐ€ ์žˆ๋Š”๊ฐ€? ex) parallelStream, CompletableFuture
ํ•ญ๋ชฉ Partitioning (Spring Batch) ParallelStream, CompletableFuture
์ ์šฉ ๊ณ„์ธต Batch Job์˜ Step ๋ ˆ๋ฒจ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋˜๋Š” ์„œ๋น„์Šค ๊ณ„์ธต
์ฃผ์š” ๋ชฉ์  ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌํ•˜์—ฌ Batch ์†๋„ ๊ฐœ์„  ์—ฐ์‚ฐ ์ตœ์ ํ™”, ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ, ์‘๋‹ต ์‹œ๊ฐ„ ๋‹จ์ถ•
ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ Spring Batch์—์„œ ์ œ๊ณต (ํŠธ๋žœ์žญ์…˜ ๋ถ„๋ฆฌ๋จ) ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๊ด€๋ฆฌํ•ด์•ผ ํ•จ
์žฌ์‹œ์ž‘ ๋ฐ ๋ณต๊ตฌ Spring Batch๊ฐ€ ์ง€์› ์ˆ˜๋™์œผ๋กœ ๊ตฌํ˜„ ํ•„์š”
์˜ค๋ฒ„ํ—ค๋“œ Spring Batch ์ปจํ…์ŠคํŠธ ๋ฐ ํŒŒํ‹ฐ์…˜ ์„ค์ • ์˜ค๋ฒ„ํ—ค๋“œ ์ƒ๋Œ€์ ์œผ๋กœ ๊ฐ€๋ณ์ง€๋งŒ ํŠธ๋žœ์žญ์…˜ ์—†์Œ
๋ณต์žก๋„ ์„ค์ •๊ณผ ํŒŒํ‹ฐ์…˜ ์ •์˜๊ฐ€ ๋ณต์žกํ•จ ๊ตฌํ˜„์ด ๋‹จ์ˆœํ•˜๊ณ  ์ง๊ด€์ 
์—๋Ÿฌ ํ•ธ๋“ค๋ง Spring Batch์—์„œ ๊ด€๋ฆฌ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ณ„๋„ ํ•ธ๋“ค๋ง ํ•„์š”
์Šค๋ ˆ๋“œ ๊ด€๋ฆฌ Spring Batch์˜ PartitionHandler ๊ด€๋ฆฌ ForkJoinPool ๋˜๋Š” ์Šค๋ ˆ๋“œ ํ’€ ์ง์ ‘ ๊ด€๋ฆฌ
์ƒํƒœ ๊ด€๋ฆฌ ExecutionContext๋ฅผ ํ†ตํ•ด ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌ ๊ณต์œ  ๋ณ€์ˆ˜๋‚˜ ์ƒํƒœ ๊ด€๋ฆฌ๋Š” ๊ฐœ๋ฐœ์ž ์ฑ…์ž„

์ฆ‰, ํŒŒํ‹ฐ์…˜ ๋ณ„๋กœ ๋…๋ฆฝ์ ์ธ SlaveStep์„ ์ƒ์„ฑํ•˜๊ธฐ ๋–„๋ฌธ์— Spring Batch์˜ ๊ด€๋ฆฌ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

  • ๋…๋ฆฝ์ ์ธ ExecutionContext๊ฐ€ ์ฃผ์–ด์ ธ ์ƒํƒœ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

Chunk

  • ๋ชฉ์  : ๊ฐ step๋‚ด์˜ ํŠธ๋ Œ์ ์…˜ ๋‹จ์œ„ ๋ถ„๋ฆฌ
  • Reader / Processor / writer ๊ฐ€ ์—ญํ• ์„ ๋ถ„๋‹ด


ํŒŒํ‹ฐ์…”๋‹ ํ๋ฆ„


ThreadPoolSize : ๋™์‹œ์— ์‹คํ–‰์‹œํ‚ฌ ์Šคํ…Œ๋ฆฌ๋“œ์˜ ๊ฐœ์ˆ˜

gridSize : ์‹ค์ œ๋กœ ์ œ๋‹จํ•  ์‚ฌ์ด์ฆˆ(์ž‘์—…๋‹จ์œ„)

QueueCapacity : ๋Œ€๊ธฐ์—ด ํฌ๊ธฐ

MaxPoolSize : ์ตœ๋Œ€ ์ถ”๊ฐ€ ์Šค๋ ˆ๋“œ ํ’€ ๊ฐœ์ˆ˜

ThreadPoolSize : 4 / gridSize : 25
MaxPoolSize : 4 / QueueCapacity : 2 (๋Œ€๊ธฐ์—ดํฌ๊ธฐ๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด Exception ๋ฐœ์ƒ)

0. 250๊ฐœ์˜ ๋ฐ์ดํ„ฐ

  1. Partition ์ƒ์„ฑ:

    • Partition 1 : ID 1 ~ 25 / ๋Œ€๊ธฐ์—ด1 : ID 101 ~ 125 / ๋Œ€๊ธฐ์—ด2 : ID 201 ~ 225
    • Partition 2 : ID 26 ~ 50 / ๋Œ€๊ธฐ์—ด : ID 126 ~ 150 / ๋Œ€๊ธฐ์—ด2 : ID 226 ~ 250
    • Partition 3 : ID 51 ~ 75 / ๋Œ€๊ธฐ์—ด : ID 151 ~ 175 / ๋Œ€๊ธฐ์—ด2 : -
    • Partition 4 : ID 76 ~ 100 / ๋Œ€๊ธฐ์—ด : ID 176 ~ 200 / ๋Œ€๊ธฐ์—ด2 : -
  2. ๊ฐ Partition์—์„œ Chunk ์ฒ˜๋ฆฌ:

    • Partition 1:
      • Chunk 1: ID 1 ~ 10 โ†’ ์ปค๋ฐ‹
      • Chunk 2: ID 11 ~ 20 โ†’ ์ปค๋ฐ‹
      • Chunk 3: ID 21 ~ 25 โ†’ ์ปค๋ฐ‹
    • Partition 2:
      • Chunk 1: ID 26 ~ 35 โ†’ ์ปค๋ฐ‹
      • Chunk 2: ID 36 ~ 45 โ†’ ์ปค๋ฐ‹
      • Chunk 3: ID 46 ~ 50 โ†’ ์ปค๋ฐ‹
    • ๋‚˜๋จธ์ง€ Partition๋„ ๋™์ผ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌ.
  3. ๋ณ‘๋ ฌ ์‹คํ–‰:

    • ์Šค๋ ˆ๋“œ ํ’€ ํฌ๊ธฐ = 4์ด๋ฏ€๋กœ 4๊ฐœ์˜ Partition์ด ๋™์‹œ์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
    • Partition ์ฒ˜๋ฆฌ ์ˆœ์„œ๋Š” ์Šค๋ ˆ๋“œ ํ’€์—์„œ ์ฒ˜๋ฆฌ๋˜๋Š” ์ˆœ์„œ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ.
  4. ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ:

    • ๊ฐ Partition์€ ๋…๋ฆฝ์ ์ธ ํŠธ๋žœ์žญ์…˜์„ ๊ฐ€์ง.
    • ๊ฐ Chunk๊ฐ€ ์ปค๋ฐ‹๋  ๋•Œ๋งˆ๋‹ค ํŠธ๋žœ์žญ์…˜์ด ์ข…๋ฃŒ๋จ.

๋ฐ์ดํ„ฐ๊ฐ€ ๋Š˜์–ด๋‚ฌ์„๋•Œ?

ThreadPoolSize : 4 / gridSize : 25
MaxPoolSize : 6 / QueueCapacity : 2 (๋Œ€๊ธฐ์—ดํฌ๊ธฐ๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด Exception ๋ฐœ์ƒ)

์‹คํ–‰ ํ๋ฆ„:

0. 500๊ฐœ์˜ ๋ฐ์ดํ„ฐ

  1. Partition ์ƒ์„ฑ:

    • Partition 1 : ID 1 ~ 25 / ๋Œ€๊ธฐ์—ด1 : ID 101 ~ 125 / ๋Œ€๊ธฐ์—ด2 : ID 201 ~ 225
    • Partition 2 : ID 26 ~ 50 / ๋Œ€๊ธฐ์—ด : ID 126 ~ 150 / ๋Œ€๊ธฐ์—ด2 : ID 226 ~ 250
    • Partition 3 : ID 51 ~ 75 / ๋Œ€๊ธฐ์—ด : ID 151 ~ 175 / ๋Œ€๊ธฐ์—ด2 : ID 251 ~ 275
    • Partition 4 : ID 76 ~ 100 / ๋Œ€๊ธฐ์—ด : ID 176 ~ 200 / ๋Œ€๊ธฐ์—ด2 : ID 276 ~ 300
    • ์ถ”๊ฐ€ ์Šค๋ ˆ๋“œ ํ’€ ์ƒ์„ฑ
    • Partition 5 : ID 300 ~ 325 / ๋Œ€๊ธฐ์—ด : ID 326 ~ 350 / ๋Œ€๊ธฐ์—ด2 : ID 351 ~ 375
    • ์ถ”๊ฐ€ ์Šค๋ ˆ๋“œ ํ’€ ์ƒ์„ฑ
    • Partition 6 : ID 376 ~ 400 / ๋Œ€๊ธฐ์—ด : ID 401 ~ 425 / ๋Œ€๊ธฐ์—ด2 : ID 426 ~ 450

    ๋ชจ๋“  ๋Œ€๊ธฐ์—ด ์†Œ๋ชจ ๋ฐ ์ตœ๋Œ€ ์Šค๋ ˆ๋“œ ํ’€ ๋„๋‹ฌ => ์ž‘์—… ์ค‘๋‹จ ๋ฐ ์˜ค๋ฅ˜



ํŒŒํ‹ฐ์…”๋‹ ์‹œ ์Šค๋ ˆ๋“œ ์„ค์ • ๋ฐฉ์‹ ์„ ํƒ


์–ด๋– ํ•œ ๋ฐฉ์‹์„ ์ ์šฉํ•˜๋Š”๊ฒŒ ์†๋„์™€ ์•ˆ์ •์„ฑ ๋ฉด์—์„œ ํšจ์œจ์ ์ผ์ง€??

์ฒ˜๋ฆฌํ•  ์ปฌ๋Ÿผ ๊ฐœ์ˆ˜๊ฐ€ ์ ์„ ๋•Œ๋Š” ์ฒญํฌ๊ฐ€ ์„ธ๋ถ„ํ™”๋˜๋”๋ผ๋„ ๋ถ€ํ•˜๊ฐ€ ํฌ์ง€ ์•Š์Œ.

-> ์ด๋กœ๋ณผ๋•Œ, ์ฟผ๋ฆฌ์ž‘์—…๋ณด๋‹ค apiํ˜ธ์ถœ์ž‘์—…์˜ ์†Œ์š”์‹œ๊ฐ„์ด ๊ธธ์–ด๋ณด์ž„

SimpleAsyncTaskExecutor vs ThreadPoolTaskExecutor
ํŠน์ง• SimpleAsyncTaskExecutor ThreadPoolTaskExecutor
์Šค๋ ˆ๋“œ ์ƒ์„ฑ ๋ฐฉ์‹ ์ž‘์—…(ํŒŒํ‹ฐ์…˜ ๋‹จ์œ„)๋งˆ๋‹ค ์ƒˆ ์Šค๋ ˆ๋“œ ์ƒ์„ฑ ์Šค๋ ˆ๋“œ ํ’€์—์„œ ์Šค๋ ˆ๋“œ๋ฅผ ์žฌ์‚ฌ์šฉ
์Šค๋ ˆ๋“œ ๊ฐœ์ˆ˜ ์ œํ•œ ์—†์Œ corePoolSize, maxPoolSize๋กœ ์ œํ•œ
๋Œ€๊ธฐ์—ด ์ง€์› ์—†์Œ ์ž‘์—… ๋Œ€๊ธฐ์—ด(queueCapacity) ์ง€์›
๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋น„ํšจ์œจ์  ํšจ์œจ์ 
์Šค๋ ˆ๋“œ ๊ด€๋ฆฌ ์—†์Œ ์Šค๋ ˆ๋“œ ํ’€๋กœ ๊ด€๋ฆฌ
์˜ค๋ฒ„ํ—ค๋“œ ์Šค๋ ˆ๋“œ ์ƒ์„ฑ/์†Œ๋ฉธ๋กœ ์˜ค๋ฒ„ํ—ค๋“œ ํผ ์Šค๋ ˆ๋“œ ์žฌ์‚ฌ์šฉ์œผ๋กœ ์˜ค๋ฒ„ํ—ค๋“œ ์ ์Œ
์ถ”์ฒœ ์‚ฌ์šฉ ์‚ฌ๋ก€ ๊ฐ„๋‹จํ•œ ์ž‘์—…, ํ…Œ์ŠคํŠธ์šฉ ๋Œ€๋Ÿ‰ ์ž‘์—…, ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ, ์•ˆ์ •์  ์ฒ˜๋ฆฌ ํ•„์š” ์‹œ

๋ฒ”์œ„ - 2017-11-07 ~ 2017-12-01
startDate=2017-11-07&endDate=2017-12-01

## ์ปฌ๋Ÿผ ๊ฐœ์ˆ˜ - 292๊ฐœ

๊ธฐ์กด ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ : 1๋ถ„ 7์ดˆ
๊ธฐ์กด๋กœ์ง : 6๋ถ„ 32์ดˆ

t:์Šค๋ ˆ๋“œ ๊ฐœ์ˆ˜ / c:๊ฐ ์Šค๋ ˆ๋“œ๋ณ„ ์ฒญํฌ ํŒŒํ‹ฐ์…˜ ์ˆ˜

###### SimpleAsyncTaskExecutor vs ThreadPoolTaskExecutor

SimpleAsyncTaskExecutor
g4/c10 : 1๋ถ„ 41.586์ดˆ
g5/c10 : 1๋ถ„ 30.037์ดˆ
g5/c3 : 1๋ถ„ 28.997์ดˆ
g5/c1 : 1๋ถ„ 29.931์ดˆ
g8/c10 : 1๋ถ„ 36.019์ดˆ
g10/c1 : 1๋ถ„ 24.529์ดˆ

-

ThreadPoolTaskExecutor
Th min/maxSize64, g64/c10 : 1๋ถ„ 42.848์ดˆ
Th min/maxSize32, g32/c10 : 1๋ถ„ 26.551์ดˆ

Th min/maxSize16, g16/c10 : 
1๋ถ„ 46.753์ดˆ / 1๋ถ„ 33.779์ดˆ / 2๋ถ„ 25.759์ดˆ
1๋ถ„ 11.668์ดˆ / 2๋ถ„ 5.773์ดˆ / 2๋ถ„ 39.553์ดˆ

Th min/maxSize32, g8/c20 : 3๋ถ„ 25.743์ดˆ

Th min/maxSize16, g4/c10 :  2๋ถ„ 29.207์ดˆ / 2๋ถ„ 8.004์ดˆ

์ •๋ฆฌ

SimpleAsyncTaskExecutor

  • Grid์‚ฌ์ด์ฆˆ(ํŒŒํ‹ฐ์…”๋‹ ๊ฐฏ์ˆ˜) ๋งŒํผ ์Šค๋ ˆ๋“œ ํ’€ ๊ณ„์† ์ƒ์„ฑ
  • ํŒŒํ‹ฐ์…”๋‹ ๊ฐฏ์ˆ˜๊ฐ€ ๋งŽ์•„์กŒ์„ ๋•Œ, ์Šค๋ ˆ๋“œ ์ƒ์„ฑ/์†Œ๋ฉธ์— ๋“œ๋Š” ์˜ค๋ฒ„ํ—ค๋“œ ์ฆ๊ฐ€

ThreadPoolTaskExecutor

  • ์ตœ์†Œ ์Šค๋ ˆ๋“œํ’€ ๊ฐœ์ˆ˜ / ์ตœ๋Œ€ ์Šค๋ ˆ๋“œํ’€ ๊ฐœ์ˆ˜ / ๋Œ€๊ธฐ์—ด ํ ํฌ๊ธฐ / ์œ ํœด ์‹œ๊ฐ„ ๋ชจ๋‘ ์„ค์ •๊ฐ€๋Šฅ
  • ํŒŒํ‹ฐ์…”๋‹ ๊ฐฏ์ˆ˜๊ฐ€ ๋งŽ์„ ๊ฒฝ์šฐ, ์ฒ˜๋ฆฌ ์„ฑ๋Šฅ์— ๋งž๋Š” ์Šค๋ ˆ๋“œ ํ’€์—์„œ ๋Œ€๊ธฐ์ž‘์—…์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ ์˜ค๋ฒ„ํ—ค๋“œ ๊ฐ์†Œ

1. ์˜ˆ์น˜๊ธˆ ์ฐจ์•ก ์ฒ˜๋ฆฌ ๊ฑด์€ ์ด ์ปฌ๋Ÿผ์ˆ˜๊ฐ€ ๋งŽ์ง€ ์•Š๋‹ค.

2. ๋ฐฐ์น˜ ํ”„๋กœ์ ํŠธ ํŠน์„ฑ์ƒ ๋™์‹œ ์ž‘์—…์„ ๊ณ ๋ คํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

  • ์ด ์ฒ˜๋ฆฌ๋Ÿ‰ ๊ธฐ์ค€ 1/n๋กœ ๊ฐ ์Šค๋ ˆ๋“œ์— ํ• ๋‹น์‹œ ์ถฉ๋ถ„ํžˆ ๊ฐ๋‹นํ•œ ์–‘์œผ๋กœ, ๋Œ€๊ธฐ์—ด์„ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

๋”ฐ๋ผ์„œ, SimpleAsyncTaskExecutor๋ฅผ ํ†ตํ•ด ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ ํ•ฉํ•˜๋‹ค๊ณ  ํŒ๋‹จํ•˜์˜€๋‹ค.


์ฒญํฌ ๋ฐฉ์‹์˜ ๋™์ž‘ ๋กœ์ง

1. ๋ฆฌ๋”๋Š” ์ฒญํฌ์‚ฌ์ด์ฆˆ ๋งŒํผ ๋ฐ˜๋ณตํ•˜๋ฉฐ, ๊ฐ ๋ฐ˜๋ณต๋งˆ๋‹ค ํŠน์ •๋ฒ”์œ„์˜ ๊ฐ’์„ returnํ•œ๋‹ค.

2. ํ”„๋กœ์„ธ์„œ๋Š” ์ฒญํฌ์‚ฌ์ด์ฆˆ์™€ ๊ด€๊ณ„์—†์ด ๋ฆฌ๋”๊ฐ€ ๋„˜๊ธด return์— ๋”ฐ๋ผ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

3. ๋กธ์ดํ„ฐ๋Š” ์ฒญํฌ์‚ฌ์ด์ฆˆ๋งŒํผ ๋ชจ์ด๋ฉด, ๊ทธ๋•Œ 1๋ฒˆ ๋™์ž‘ํ•œ๋‹ค.



QuerydslPagingItemReader ์ ์šฉ๊ธฐ


ItemReader ๋ฐฉ์‹

  • ์ฟผ๋ฆฌ ํ˜ธ์ถœ ๋ฐ ํŽ˜์ด์ง• ๊ธฐ๋ฒ• ์ง์ ‘ ๊ตฌํ˜„

PagingItemReader ๋ฐฉ์‹

  • Native Query ํ˜•ํƒœ๋กœ ํ˜ธ์ถœํ•˜์—ฌ ์ž๋™ ํŽ˜์ด์ง•

QuerydslPagingItemReader (์ปค์Šคํ…€) ๋ฐฉ์‹

  • Spring Batch์—์„œ๋Š” ๊ณต์‹์ ์œผ๋กœ ์ง€์›ํ•˜์ง€ ์•Š์Œ
  • ์ž๋™ ํŽ˜์ด์ง•
  • Querydslํ˜•ํƒœ๋กœ ์ฟผ๋ฆฌ ํ˜ธ์ถœ ๊ฐ€๋Šฅ

QuerydslPagingItemReader ๋ฐฉ์‹ ๊ตฌํ˜„ ๋ชฉ์ 

  • ๊ธฐ์กด(ํ—ฌ๋กœ)์˜ Querydsl๊ธฐ๋ฐ˜ JPAQuery๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • ์ž๋™ ํŽ˜์ด์ง•
  • ๊ทธ ์™ธ Querydsl์˜ ์žฅ์  ๋ณด์œ 

AbstractPagingItemReader๋ฅผ ์ƒ์†๋ฐ›๋Š” ์ปค์Šคํ…€ QuerydslPagingItemReader ํด๋ž˜์Šค ์ƒ์„ฑ

  • ๊ธฐ์กด PagingItemReader์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋ฉฐ, JPQL์ด ์ˆ˜ํ–‰๋˜๋˜ ๋ถ€๋ถ„์— ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜์˜€๋‹ค.

๊ตฌํ˜„๋œ Reader

@Bean  
@Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS)  
public QuerydslPagingItemReader<HfbatBankBalanceCheckDto> balanceReader() {  
    ExecutionContext jobContext = Objects.requireNonNull(StepSynchronizationManager.getContext()).getStepExecution().getJobExecution().getExecutionContext();  
    Date startDate = (Date) jobContext.get(START_DATE_KEY);  
    Date endDate = (Date) jobContext.get(END_DATE_KEY);  
    return new QuerydslPagingItemReader<>(  
            entityManagerFactory,  
            executionOrder,  
            DEFAULT_CHUNK_SIZE,  
            queryFactory -> repository.newFindChangeBalanceMemberList(  
                    startDate,  
                    endDate  
            ));  
}


QuerydslPagingItemReader๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ๋‹ค์ค‘์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋ง ํ•˜๊ธฐ


๋ชฉ์ 

  • ๊ฐ ํŒŒํ‹ฐ์…˜ ์Šค๋ ˆ๋“œ ๋ณ„ ์ข…๋ฃŒ ์‹œ๊ฐ„์ด ํฌ๊ฒŒ ์ƒ์ดํ•˜๋‹ค. ์ด ์†Œ์š”์‹œ๊ฐ„ ๊ธฐ์ค€ ์ตœ๋Œ€ ์•ฝ 20% ์ฐจ์ด
  • ์ ์šฉ ํ•œ๋‹ค๋ฉด, ๊ฐ ์Šค๋ ˆ๋“œ ๋ณ„๋กœ evenํ•˜๊ฒŒ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ์ด ์†Œ์š”์‹œ๊ฐ„์„ ์ค„์ผ ์ˆ˜ ์žˆ์„๊ฒƒ์ด๋ผ ํŒ๋‹จ

๊ตฌํ˜„ ๋ฐฉ๋ฒ•

JOB

private static AtomicLong executionOrder = new AtomicLong(0);

...

new QuerydslPagingItemReader<>(  
        entityManagerFactory,  
        executionOrder,  
        DEFAULT_CHUNK_SIZE,  
        queryFactory -> repository.newFindChangeBalanceMemberList(  
                startDate,  
                endDate  
        ));
  • job ๋ ˆ๋ฒจ์—์„œ์˜ ์Šค๋ ˆ๋“œ ์„ธ์ดํ”„ํ•œ ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜์˜€๋‹ค.
  • ๊ทธ ํ›„, ๊ฐ ํŒŒํ‹ฐ์…˜ ๋ณ„ ๋ฆฌ๋”์— ์ธ์ž๊ฐ’์œผ๋กœ ๋„˜๊ธด๋‹ค.
long currentExecutionOrder = executionOrder.getAndIncrement();  
long startIndex = (currentExecutionOrder) * getPageSize();  
int totalRecords = stepContext.getInt("totalRecords");  
  
if (startIndex >= totalRecords) {  
    initResults(); // ๋นˆ ๊ฒฐ๊ณผ๋กœ ์ดˆ๊ธฐํ™”  
    tx.commit();  
    return;  
}  
  
int chunkSizeToRead = Math.min(getPageSize(), (int) (totalRecords - startIndex)); // ๋‚จ์€ ๋ฐ์ดํ„ฐ ํฌ๊ธฐ๋งŒํผ ์ฝ๊ธฐ  
  
// QueryDSL Query ์ƒ์„ฑ  
JPQLQuery<T> query = createQuery()  
        .offset(startIndex)  
        .limit(chunkSizeToRead);

์Šค๋ ˆ๋“œ ์„ธ์ดํ”„ํ•œ ํ•ด๋‹น ๋ณ€์ˆ˜๋Š” ๊ฐ ํŽ˜์ด์ง• ๋ฆฌ๋”์˜ startIndex๋ฅผ ์ง€์ • ํ•œ ํ›„,

์ฆ‰์‹œ ๊ฐ’์„ ๋Š˜๋ฆฐ๋‹ค. getAndIncrement()

ํšจ๊ณผ

  • ๋จผ์ € ํ•œ ์ฒญํฌ๋‹จ์œ„์˜ ์ž‘์—…์„ ๋๋‚ธ ํŒŒํ‹ฐ์…˜์€ ๊ทธ ๋‹ค์Œ ์ž‘์—…์„ ์ฆ‰์‹œ ํ• ๋‹น๋ฐ›๊ฒŒ ๋œ๋‹ค.
  • ์ฆ‰, ์ด ์ฒ˜๋ฆฌ์‹œ๊ฐ„ ๊ธฐ์ค€ ๊ฐ€์žฅ ๋นจ๋ฆฌ๋๋‚œ ํŒŒํ‹ฐ์…˜๊ณผ ๊ฐ€์žฅ ๋Šฆ๊ฒŒ ๋๋‚œ ํŒŒํ‹ฐ์…˜์˜ ์‹คํ–‰ ์‹œ๊ฐ„ ์ฐจ์ด๋Š” ์ตœ๋Œ€ ํ•œ ์ฒญํฌ์‚ฌ์ด์ฆˆ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์‹œ๊ฐ„๋ณด๋‹ค ํฌ์ง€ ์•Š๊ฒŒ ๋œ๋‹ค.


๋ฉ”์„ธ์ง• ์ฒ˜๋ฆฌ ๋กœ์ง ๋ถ„๋ฆฌ


1. ๋กœ์ง์ˆœ์„œ

๋ฉ”์„ธ์ง• ์ฒ˜๋ฆฌํ•  ๋ฐ์ดํ„ฐ

1์ฐจ ๋น„๊ต ์ดํ›„ ์ฐจ์•ก์ด ๋ฐœ์ƒํ•œ ๋…€์„๋“ค์˜ List ๋ฅผ ํ•œ๋ฒˆ ๋” ๊ฒ€์ฆํ•œ ํ›„, => ์ถ”ํ›„ ๋ณ€๊ฒฝ ๋จ ๊ฒ€์ฆ๋œ ๋…€์„๋“ค์„

List<BalanceCheckResultDto> realDiffList= new ArrayList<>();

์ตœ์ข…์ ์ธ ์ฐจ์•ก ๋ฆฌ์ŠคํŠธ์— ๋„ฃ๋Š”๋‹ค.

์Šค๋ ˆ๋“œ ๋ณ„๋กœ ๋”ฐ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ๋…€์„๋“ค์„ processor์˜ ๋ฆฌํ„ด์œผ๋กœ writer์—๊ฒŒ ๋„˜๊ธด๋‹ค.

writer๋Š” ๊ฐ ํ”„๋กœ์„ธ์„œ์˜ ๋ฆฌํ„ด์œผ๋กœ ๋ฐ›์€ ๋…€์„๋“ค์„ ํ•˜๋‚˜์˜ DTO List๋กœ ํ•ฉ์ณ ๋ฉ”์„ธ์ง• ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ฒŒ ๋œ๋‹ค.


2. ์–ด๋–ป๊ฒŒ ๋ฉ”์„ธ์ง€(DTO ๋ฐ์ดํ„ฐ)๋ฅผ ์ทจํ•ฉํ•  ๊ฒƒ์ธ๊ฐ€?

์ „์—ญ์œผ๋กœ ๊ฐ์ฒด๋ฅผ ์„ ์–ธํ•˜์—ฌ appendํ•˜๋Š” ๋ฐฉ์‹์€ ์Šค๋ ˆ๋“œ ์„ธ์ดํ”„ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฐ์ œํ•˜์˜€๋‹ค.

๋ฐฉ๋ฒ• 1. ์™ธ๋ถ€์ €์žฅ์†Œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

  • ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ์ข‹๋‹ค.
  • ํ™˜๊ฒฝ์…‹ํŒ…์— ๋ฆฌ์†Œ์Šค๊ฐ€ ๋งŽ์ด๋“ ๋‹ค.

๋ฐฉ๋ฒ• 2. ExecutionContext์— DTO๋ฅผ ์ง๋ ฌํ™” ์‹œ์ผœ ์ €์žฅํ•œ๋‹ค.

  • ๊ตฌํ˜„ ๋ ˆ๋ฒจ์ด ๊ฐ€์žฅ ์‰ฝ๋‹ค
  • DTO(๋ฐ์ดํ„ฐ)๊ฐ€ ๋งŽ์•„์งˆ ๊ฒฝ์šฐ, ํฐ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐจ์ง€ํ•œ๋‹ค.

๋ฐฉ๋ฒ• 3. DTO๋ฅผ ๋ถ„ํ•ดํ•˜์—ฌ ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ๋งŒ ์ €์žฅํ•œ๋‹ค.

  • ๋ฐฉ๋ฒ• 2.๋ณด๋‹ค๋Š” ๋ฆฌ์†Œ์Šค๊ฐ€ ์ ์ง€๋งŒ, ๋ฌธ์ž์—ด ์ฒ˜๋ฆฌ ์‹œ๊ฐ„์ด ์ถ”๊ฐ€๋กœ ์†Œ๋ชจ๋œ๋‹ค.

๋ฐฉ๋ฒ• 4. ConcurrentLinkedQueue ์‚ฌ์šฉ (์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•œ ํ ์ž๋ฃŒ๊ตฌ์กฐ)

  • ๋†’์€ ์“ฐ๊ธฐ ์„ฑ๋Šฅ์„ ๊ฐ–๊ณ ์žˆ๋‹ค.
  • ๋™์‹œ์„ฑ ๋ฌธ์ œ ์—†์ด ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์ธ๋ฑ์Šค๋กœ ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

ํ•ด๋‹น ๋ฐฉ๋ฒ•๋“ค์„ ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์™€ ๋น„๊ตํ–ˆ์„ ๋•Œ, ๋ฐฉ๋ฒ• 4.๊ฐ€ ํ•ฉ๋ฆฌ์ ์œผ๋กœ ๋ณด์ธ๋‹ค.

QueueManagerํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๋ฉฐ ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•˜์˜€๊ณ ,

@Slf4j  
public class QueueManager<T> {  
    protected final ConcurrentLinkedQueue<T> sharedQueue = new ConcurrentLinkedQueue<>();  
  
    // ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€  
    public void addItemToSharedQueue(T item) {  
        if (item != null) {  
            sharedQueue.add(item);  
        }  
    }

์ด๋ฅผ ์ƒ์†๋ฐ›์•„ ํŠน์ • ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๋‹ค.

public class BalanceQueue extends QueueManager<BalanceCheckResultDto>{  
  
    public List<BalanceCheckResultDto> getDtoFromQueue() {  
        return super.getItemsFromQueue();  
    }  
}


Listener ์—ญํ•  ๋ถ„๋ฆฌ


* Listener์— ํฌํ•จ๋œ ์ดˆ๊ธฐํ™” ์ฝ”๋“œ ๋ฐ ๋กœ๊ทธ ๋กœ์ง

Pasted image 20241217150339.png

  • ๋ฆฌ์Šค๋„ˆ์— ๋„ˆ๋ฌด ๋งŽ์€ ์—ญํ• ์ด ๋ถ€์—ฌ๋œ ๋ชจ์Šต

ํŒŒํ‹ฐ์…˜ ํ•ธ๋“ค๋Ÿฌ์˜ grid์‚ฌ์ด์ฆˆ๋ฅผ ๋™์ ์œผ๋กœ ํ• ๋‹นํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ•„์š”ํ•œ ์ž‘์—….

ํŒŒํ‹ฐ์…˜ ํ•ธ๋“ค๋Ÿฌ์˜ ์ƒ์„ฑ ์‹œ์ ์„ ๋ช…ํ™•ํžˆ ํ•œ ํ›„์—, ๋ฆฌ์Šค๋„ˆ์—์„œ ์ฃผ์ž…ํ•˜๋˜ ์ฝ”๋“œ๋ฅผ STEP์œผ๋กœ ๋ถ„๋ฆฌํ•˜์˜€๋‹ค.

Pasted image 20241219145746.png

๊ธฐ์กด SteoExecution์—์„œ JobExecution์œผ๋กœ ํ•˜๋‚˜์˜ Job์—์„œ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณ€๊ฒฝํ•˜์—ฌ gridSize๋ฅผ ๋‹ค์Œ Step์—์„œ ๊ฐ€์ ธ์˜ฌ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๋‹ค.

๋น„๊ต: JobParameters vs ExecutionContext`

ํŠน์ง• JobParameters ExecutionContext
์ฝ๊ธฐ/์“ฐ๊ธฐ ์—ฌ๋ถ€ ์ฝ๊ธฐ ์ „์šฉ ์ฝ๊ธฐ/์“ฐ๊ธฐ ๊ฐ€๋Šฅ
๊ณต์œ  ๋ฒ”์œ„ Job ์ „์ฒด์—์„œ ๊ณต์œ  Step ๋˜๋Š” Job ์ „์ฒด์—์„œ ๊ณต์œ  ๊ฐ€๋Šฅ
์šฉ๋„ ์‹คํ–‰ ์‹œ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ „๋‹ฌ ์‹คํ–‰ ์ค‘ ์ƒํƒœ ์ €์žฅ, ๋ฐ์ดํ„ฐ ๊ณต์œ 
์ˆ˜๋ช… JobInstance์™€ ํ•จ๊ป˜ ์œ ์ง€ StepExecution ๋˜๋Š” JobExecution๊ณผ ํ•จ๊ป˜ ์œ ์ง€
Restart ์‹œ ์œ ์ง€ ์—ฌ๋ถ€ ํ•ญ์ƒ ์œ ์ง€๋จ Restart ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๋งŒ ์œ ์ง€

StepExecution vs JobExecution

  • StepExecution-Level ExecutionContext
    • ๊ฐ Step์— ๊ณ ์œ ํ•œ ExecutionContext๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

    • Step ๋‚ด์˜ Reader, Processor, Writer ๋“ฑ์—์„œ ๊ณต์œ ๋ฉ๋‹ˆ๋‹ค.

    • ๋‹ค๋ฅธ Step๊ณผ๋Š” ๊ณต์œ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    • balanceWorkerStep ๋‚ด์—์„œ๋Š” Reader, Processor, Writer๊ฐ€ ๋™์ผํ•œ ExecutionContext๋ฅผ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

    • balancePartitionStep๊ณผ balanceWorkerStep์˜ ExecutionContext๋Š” ์„œ๋กœ ๋…๋ฆฝ์ ์ž…๋‹ˆ๋‹ค.

  • JobExecution-Level ExecutionContext
    • Job ์ „์ฒด์—์„œ ๊ณต์œ ๋˜๋ฉฐ, ๋ชจ๋“  Step์ด ๋™์ผํ•œ ExecutionContext์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • JobExecutionContext๋Š” Step ๊ฐ„ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์ด ํ•„์š”ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์—ญํ• ์ด ๋ถ„๋ฆฌ๋œ ๋ฆฌ์Šค๋„ˆ๋Š” ์žฌ์‚ฌ์šฉ์„ ์œ„ํ•ด ์ปค์Šคํ…€ ํด๋ž˜์Šค๋กœ ์ƒ์„ฑ

JobExecutionListener ๊ฐ์ฒด ์ƒ์„ฑ

@Slf4j  
public class JobTimerExecutionListener implements JobExecutionListener {  
    private final String jobName;  
    private long startTime = System.currentTimeMillis();  
  
    public JobTimerExecutionListener(String jobName) {  
        this.jobName = jobName;  
    }  
  
    @Override  
    public void beforeJob(JobExecution var1) {  
        startTime = System.currentTimeMillis();  
    }  
  
    @Override  
    public void afterJob(JobExecution var1) {  
        long endTime = System.currentTimeMillis();  
        long elapsedTime = endTime - startTime;  
        long minutes = (elapsedTime / 1000) / 60; // ๋ฐ€๋ฆฌ์ดˆ๋ฅผ ๋ถ„์œผ๋กœ ๋ณ€ํ™˜  
        double seconds = (elapsedTime / 1000.0) % 60; // ๋‚จ์€ ๋ฐ€๋ฆฌ์ดˆ๋ฅผ ์ดˆ๋กœ ๋ณ€ํ™˜ (์†Œ์ˆ˜์  ํฌํ•จ)  
        log.info("{}-completed: {} ms | {} minutes {} seconds", jobName, elapsedTime, minutes, seconds);  
    }  
}

์˜ˆ์น˜๊ธˆ ๋ฐฐ์น˜ ๊ตฌ์กฐ๋„

์„ฑ๊ณผ


์˜ˆ์น˜๊ธˆ์ฐจ์•ก๋น„๊ต Batch Job ๊ธฐ์กด ์†Œ์š”์‹œ๊ฐ„ ๊ทธ๋ž˜ํ”„

2024-10-28 ~ 2024-11-19 (์ฃผ๋ง์ œ์™ธ)

  • ํ‰๊ท  ์†Œ์š”์‹œ๊ฐ„: ์•ฝ 17.35๋ถ„
  • ์ตœ๋Œ€ ์†Œ์š”์‹œ๊ฐ„: 22๋ถ„
  • ์ตœ์†Œ ์†Œ์š”์‹œ๊ฐ„: 12๋ถ„ output (1).png

๋ณ€๊ฒฝ ํ›„ Batch ์ด ์†Œ์š”์‹œ๊ฐ„ ๋น„๊ต ๊ทธ๋ž˜ํ”„

output (9) 1.png

ํ‰๊ท  ์ด ์†Œ์š”์‹œ๊ฐ„

๊ธฐ์กด๋กœ์ง : 13.27๋ถ„
์‹ ๊ทœ๋กœ์ง : 4.77๋ถ„

1์ปฌ๋Ÿผ๋‹น ์†Œ์š”์‹œ๊ฐ„ ๊ทธ๋ž˜ํ”„

output (10).png

1์ปฌ๋Ÿผ ๋‹น ์†Œ์š”์‹œ๊ฐ„

๊ธฐ์กด๋กœ์ง : 3.74์ดˆ
์‹ ๊ทœ๋กœ์ง : 0.72์ดˆ

grid-size : 6 ๊ธฐ์ค€

๊ธฐ์กด๋กœ์ง ๋Œ€๋น„

์ด ์†Œ์š”์‹œ๊ฐ„ 64.05% ๊ฐ์ถ•

1์ปฌ๋Ÿผ๋‹น ์ฒ˜๋ฆฌ์‹œ๊ฐ„ 80.75% ๊ฐ์ถ•

1ํŠธ๋ Œ์ ์…˜ ์ตœ๋Œ€ ์ฒ˜๋ฆฌ์‹œ๊ฐ„ 99.91% ๊ฐ์ถ•


Grid-Size์— ๋”ฐ๋ฅธ ์ ์œ  ์ปค๋„ฅ์…˜ ํ’€ ๋ฐ ์†Œ์š”์‹œ๊ฐ„

do-messenger_screenshot_2024-12-23_14_40_21.png

grid-size๋ฅผ ๋™์ ์œผ๋กœ ๋Š˜๋ ค๊ฐ์— ๋”ฐ๋ผ ์ด ์†Œ์š”์‹œ๊ฐ„์„ ๋”์šฑ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.


API ๋ถ€ํ•˜ ๊ฒ€์ฆ Elastic APM

Pasted image 20241224093159.png Pasted image 20241224093207.png Pasted image 20241224093225.png


ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… ๊ณผ์ • ๋ณด๋Ÿฌ๊ฐ€๊ธฐ โ—€