f-lab-edu / league-of-legends-data-solution

‘리그 오브 레전드’를 벤치마킹해서 플레이어의 행동 이벤트를 발생하는 API를 통해 실시간으로 데이터가 잘 흐를 수 있도록 데이터 솔루션을 제공합니다.
2 stars 0 forks source link

스파크 및 에어플로우 등등 최적화 기준에 대한 문제 #43

Closed Ra99it closed 1 month ago

Ra99it commented 2 months ago

개요

Spark 및 Airflow를 최적화를 진행하기 위해선 기준이 필요하다고 판단됩니다. 기준이 없을 땐 해당 작업을 하기 위해 최적화를 하기 위한 근거있는 판단이 어려운 거 같습니다.

그래서 다음과 같이 설정합니다.

  1. 24시간 수집되는 데이터의 양은 1,300,000개의 데이터가 수집됩니다.
  2. 평균 동시 접속자는 1,000명입니다.

Batch

일일 데이터는 1,300,000개(+- 100,000)의 데이터를 기준으로 배치 처리를 진행합니다.

Streaming

실시간 처리는 1,000명(+- 1,000)의 데이터를 기준으로 실시간 처리를 진행합니다.

기준은 변경될 수 있습니다.

Ra99it commented 1 month ago

실시간 처리 어플리케이션 리소스

EMR 환경은 Terraform로 구성되어 있습니다.

1000명 기준

Streaming Query

Streaming_1

17분 58초 간 실행되어 있으며, Avg Input은 69.80개와 Avg Process는 1633.20개로 구성되어 있습니다.

현재 입력 처리 속도와 처리 속도가 상당히 많은 차이를 나타내고 있습니다. 이는 시스템에서 초당 69.80개의 데이터를 입력받고 있지만 초당 1633개의 데이터를 처리할 수 있음을 나타냅니다.

Streaming_2

Streaming 쿼리의 상세 정보 및 18분 53초 동안 26개의 배치를 성공했습니다.

Streaming_3

  1. 입력 속도가 약 80 ~ 100 records/sec으로 일정하게 시스템에서 입력 데이터를 처리하고 있습니다.

  2. 처리 속도가 약 2000 ~ 3000 records/sec으로 높은 성능을 나타내고 있습니다.

  3. 각 배치 당 6,000건을 처리하고 있습니다.

  4. 배치 처리 시간 간격이 5000ms로 일정한 수준을 유지하고 있습니다.

Streaming_4

연산 및 작업에 대한 소요 시간을 일정하게 유지하고 있습니다.


시스템에서 입력받는 데이터에 비해 과도한 리소스 자원을 할당받고 있다고 판단됩니다. 실시간 환경에선 여유로운 리소스와 짧은 지연 시간은 중요하지만 너무 과도하다고 판단하고 있습니다. 이는 운영 단계에서 규모의 비해 훨씬 많은 운영 비용이 발생 할 것으로 예상됩니다.

Ganglia

화면 캡처 2024-10-05 164228

Streaming 실행 시작과 종료는 비교적으로 높은 CPU 사용량을 보여주고 있습니다. 대략적으로 30 ~ 40%의 사용량을 나타냅니다. 실제로 데이터를 처리하는 부분은 5 ~ 20%의 사용량을 보여주고 있습니다. CPU의 절반 이상이 유후 상태를 유지하고 있습니다.

클러스터_메모리

오토 스케일링으로 초기 단계에 총 Memory의 값은 190G까지 할당되었다가 다시 리소스 조정이 되면서 61.9G로 재조정되었습니다. 13.8G가 사용 중이며, 10.6G가 캐싱으로 할당되어 있습니다. 37.5G가 사용 가능입니다.

클러스터_과거

지난 한 시간동안 클러스터의 부하를 나타내는 지표입니다.

Streaming이 실행되는 시작과 종료를 제외하곤 일정한 수준을 유지하고 있습니다.


전체적으로 봤을 때 너무 많은 리소스를 가지고 있습니다. CPU는 50 ~ 95% 까지 유후 상태를 유지하고 있으며 메모리도 절반을 사용하지 않는 것으로 보입니다. 오버 스펙으로 인해 지속적으로 운영 할 경우 스케일링의 어려움이 있고, 비용이 증가하며 리소스가 낭비되어 이를 해결하기 위해 조정이 필요 해 보입니다.

Ra99it commented 1 month ago

스파크 Batch 처리 애플리케이션에 대한 리소스 최적화를 진행해 봅니다.

Case 1

쿼리 최적화 및 Partitions, 리소스 설정을 하지 않은 채로 실행해 봅니다.

스파크는 기본적으로, 리소스를 효율적으로 활용하도록 자동으로 리소스 할당을 합니다. 이는 적절한 성능을 얻을 수 있지만 애플리케이션의 특성에 따라서 수동으로 리소스를 설정하는 것이 훨씬 좋은 성능을 발휘할 수 있습니다.

1

Driver Memory : 2G Executor Memory : 4743M Executor Cores : 2 를 최종적으로 할당했습니다.

Dirver의 Task Time은 1.1분 그리고 Executor의 Task Time은 1.4분을 기록했습니다.

해당 최적화는 Executor의 Task Time을 줄여 데이터 처리 측면의 시간을 줄이는 것을 목표로 합니다.

image

Stages의 상태입니다. 적절한 성능을 나타내고 있습니다.

특정 Stage는 많은 Task를 가지고 있습니다. 데이터의 크기를 생각하면 Task의 수가 많은 편이고, 이는 Partitions의 크기가 작게 됩니다. 불필요한 네트워킹 및 IO가 발생할 수 있는 가능성이 있어 보입니다.

이를 통해 적절한 성능을 보여주고 있지만, 최적화가 필요한 상태라고 보입니다.

분류 Case 1
Driver Memory 2G
Executor Cores 2
Executor Memory 4743M
Num Executor 1
Driver Task Time 1.1m
Executor Task Time 1.4m

Case 2

Executor의 자원 할당을 조절해 봅니다.

m5.xlarge는 4개의 vCore와 16G Memory를 가지고 있습니다.

Case 1은 2개의 Core를 사용했기 때문에 데이터 처리 속도의 향상을 위해 Core의 수를 증가해 봅니다.

image

Driver Memory : 2G Executor Memory : 5G Executor Cores : 3으로 변경했습니다.

예측과 다르게 Task Time이 1.4m에서 2m로 증가했습니다.

image

실행 시간인 duration의 시간 차이는 Case 1과 크게 차이 나지 않습니다.

Core의 수를 4로 증가시켜 보겠습니다.

image

마찬가지로, Task Time이 증가했습니다. 실제 실행되는 시간은 크게 차이가 나지 않지만, Task Time은 Core가 증가함에 따라 증가하는 패턴을 보이고 있네요.

그러면, Core의 수를 1로 줄이면 어떻게 될까요?

image

당황스럽게 Task Time이 1m이 나왔습니다.

Stages를 한번 보겠습니다.

image

기존의 2 ~ 4개와는 다르게 duration이 높게 측정 되었습니다. 실행 시간이 증가했지만 Task Time은 줄어들었습니다. 흠...

분류 Case 2 Case 2 Case 2
Driver Memory 2G 2G 2G
Executor Cores 3 4 1
Executor Memory 5G 5G 5G
Num Executor 1 1 1
Driver Task Time 1.1m 1.0m 1.4m
Executor Task Time 2m 2.6m 1.0m

위 지표를 보면서, 추측을 해보자면 데이터의 크기가 367.6 MiB로 작은 크기를 가지고 있습니다. 크기가 작기 때문에 1 Core 만으로 처리할 수 있는 작업입니다. 1개의 Core로 처리가 가능한 작업을 Core의 수를 증가시키면 오히려 스케줄링 과정과 네트워크 I/O로 인해 오버헤드가 발생해 Task Time이 증가하게 됩니다. 즉 해당 작업은 Core를 증가시키는 것은 오히려 비효율적입니다.

Case 3

Partitions의 수를 조정 해 봅니다.

과도하게 Shuffle Partitions의 수를 200으로 설정합니다.

image

Task Time이 1분에서 56초로 단축됐습니다.

image

Stages를 보면, Shuffle Partitions를 200으로 설정했지만, 현재 6으로 설정이 되었습니다.

image

셔플이 진행되고, AQE로 인해 자동적으로 Partitions의 수가 6으로 지정되었습니다. 아무래도 Partitions의 수가 너무 많아서 이를 자동으로 병합을 진행한 거 같습니다.

그러면 Partitions의 수를 4로 조정 해보겠습니다.

image

Task Time이 감소됐고, AQE는 발생하지 않았습니다. Shuffle Partitions이 정상적으로 적용이 되었습니다.

이 후 Partitions의 수를 변화를 줘도 Task Time이 감소되지 않았습니다.


분류 Case 1 Case 2 Case 3
Driver Memory 2G 2G 2G
Executor Cores 2 1 1
Executor Memory 4743M 5G 4 ~5G
Num Executor 1 1 1
Driver Task Time 1.1m 1.4m 1.3m
Executor Task Time 1.4m 1.0m 55s

여러 번의 파라미터를 수정을 한 후 Case 3가 해당 작업의 최적화 된 리소스 설정으로 도출되었습니다.

Ra99it commented 1 month ago

마찬가지로, Train Batch 처리에 대해 리소스 최적화를 진행 해 봅니다.

Case 1

아무런 옵션 지정 없이 실행시킵니다.

image

Spark는 자동적으로

Driver Memory : 2G Executor Cores : 2 Executor Memory 4743M

를 할당했습니다.

할당된 리소스를 기반으로 적절한 성능을 나타내고 있습니다. Executor의 Task Time은 1.3m으로 나왔습니다.

image

Stages를 보면 총 Duration은 30s이며, 셔플 단계에서 26개의 Partitions로 나눠집니다.

분류 Case 1
Driver Memory 2G
Executor Cores 2
Executor Memory 4743M
Num Executor 1
Driver Task Time 1.1m
Executor Task Time 1.3m

Case 2

Core의 수를 증가시킵니다.

image

리소스 사용량은 Case 1과 비슷합니다. 하지만 Task Time에서 많은 차이를 보이고 있습니다.

image

Case 1과 마찬가지로 Duration은 30초입니다. 즉 Core가 증가해도 데이터 처리 측면의 성능 향상은 보이지 않는 거 같습니다. 오히려 병렬 처리로 인해 오버헤드가 발생 해 Task Time에 영향이 가는 거 같습니다.

다시 Core의 수를 증가시킵니다.

image

Peak Jvm의 사용량이 눈에 띄게 감소했습니다. 하지만 Task Time은 Case 1과 비교해서 많은 시간을 소비하고 있습니다.

image

하지만 기존 Duration의 30초에서 27초로 감소했습니다.

이렇듯 Core가 증가함에 따라 데이터 처리 성능의 차이는 크지 않지만 오히려 오버헤드가 발생 해 Task Time이 길어지는 패턴이 발생하게 됩니다.

그러면 Core의 수를 1로 조정해봅니다.

image

Task Time에서 큰 차이를 보이고 있습니다. 하지만

image

Duration의 시간은 증가했습니다. 1개의 코어로 인해 데이터를 처리하는 시간이 늘어났지만 Task Time에서 큰 차이를 보이고 있습니다.

Anaysis와 마찬가지로, Core의 수를 1개로 설정하는 것이 해당 작업이 더 적은 리소스와 좋은 성능을 가지도록 합니다.

분류 Case 2 Case 2 Case 2
Driver Memory 2G 2G 2G
Executor Cores 3 4 1
Executor Memory 4G 4G 4G
Num Executor 1 1 1
Driver Task Time 1.1m 1.0m 1.5m
Executor Task Time 1.9m 2.5m 1.1m

Case 3

Partitions의 수를 2 ~ 8 사이는 모두 Task Time을 1.0m을 기록했습니다.

Ra99it commented 1 month ago

K-Means를 사용 해 학습하는 ML 처리에 대한 리소스 최적화를 진행 해 보겠습니다.

Case 1

image

Spark는 기본적으로 Driver Memory : 2G Executor Cores : 2 Executor Memory 4743M 를 할당했습니다.

할당된 리소스를 기반으로, 리소스를 초과하지 않고 적절하게 사용하고 있습니다.

Task Time은 1.4m을 기록했습니다.

image

생각보다 Duration은 굉장히 짧은 편 입니다.

분류 Case 1
Driver Memory 2G
Executor Cores 2
Executor Memory 4743M
Num Executor 1
Driver Task Time 1.0m
Executor Task Time 1.4m

Case 2

Core의 수를 3으로 설정합니다.

image

다른 작업과 비슷하게 Task Time이 늘어나는 패턴을 보이고 있습니다. Duration도 비슷합니다.

Core의 수를 4로 설정합니다.

image

Task Time이 늘어납니다. 또한 Shuffle Read Write의 크기가 너무 작다고 생각합니다.

코어가 증가함에 따라 Duration은 큰 차이가 나지 않지만, Task Time은 오버헤드로 인해 늘어나게 됩니다.

그러면 Core의 수를 1로 설정 해 보겠습니다.

image

image

Duration은 조금 증가했지만, Task Time에서 큰 차이를 보이고 있습니다.

분류 Case 2 Case 2 Case 2
Driver Memory 2G 2G 2G
Executor Cores 3 4 1
Executor Memory 4G 4G 4G
Num Executor 1 1 1
Driver Task Time 1.1m 59s 1.3m
Executor Task Time 1.8m 2.2m 1.0m

Case 3

Analysis와 Train 과는 다르게 Input의 크기가 상대적으로 큽니다.

그래서 이전과 다르게 Exeuctor의 수를 조정 해 보도록 합니다.

image

Duration은 크게 차이 나지 않지만 Task Time에서 크나큰 차이를 보이고 있습니다.

기존엔 하나의 Executor에서 약 6G에 해당되는 데이터를 입력 받아 처리했다면, Case 3는 Executor을 2개로 나눠 각각의 약 3G를 나눠 처리에 더욱 효율적으로 Task Time이 형성되었습니다.

분류 Case 3
Driver Memory 2G
Executor Cores 1
Executor Memory 2G
Num Executor 2
Driver Task Time 1.2m
Executor Task Time 50s

분류 Case 1 Case 2 Case 3
Driver Memory 2G 2G 2G
Executor Cores 2 1G 1G
Executor Memory 4743M 4G 2G
Num Executor 1 1 2
Driver Task Time 1.0m 1.3m 1.2m
Executor Task Time 1.4m 1.0m 50s
Ra99it commented 1 month ago

Gold Layer에 대한 처리 어플리케션를 리소스 최적화를 진행합니다.

Case 1

아무런 지정을 하지 않은 채 Spark가 자동으로 할당하도록 합니다.

image

이전과는 다른 형상을 띄고 있습니다. 대략적으로 봤을 땐 작업에 비해 리소스가 과하게 할당이 되었습니다.

Driver Memory : 2G Executor Cores : 4 Executor Memory: 약 9G 를 할당했습니다.

정작 JVM은 할당된 4.8G 중 최고 397.4MB를 기록했습니다. 너무 과도한 리소스가 잡혀 GC의 시간이 6초 발생이 됐습니다. Task Time은 58초입니다.

전반적으로 봤을 때 Core의 수와 Memory의 대한 조정이 필요 해 보입니다.

분류 Case 1
Driver Memory 2G
Executor Cores 4
Executor Memory 약 9 ~ 9.5
Num Executor 1
Driver Task Time 45s
Executor Task Time 58s

Case 2

Core의 수를 3으로 조정하고, Memory를 2G로 조정합니다.

image

Task Time 58초에서 53초로 감소했고, GC의 시간도 감소했습니다. 데이터를 처리하는 duration도 차이점이 크게 있지 않습니다.

Core의 수를 4로 증가시켜 봅니다.

image

Task Time이 1.2분으로 증가했으며, GC 발생 시간은 똑같습니다.

마찬가지로, Core의 수가 증가하면, Task Time도 증가합니다.

Core의 수를 1로 조정합니다.

image

Task Time과 GC 모두 눈에 띄게 감소했습니다.

분류 Case 2 Case 2 Case 2
Driver Memory 2G 2G 2G
Executor Cores 3 4 1
Executor Memory 2G 2G 2G
Num Executor 1 1 1
Driver Task Time 41s 41s 45s
Executor Task Time 53s 1.2m 24s

Case 3

한번 Executor의 2개로 변경 해 봅니다.

image

ML과 다르게 Task Time이 개선되지 않고, 오히려 증가했습니다. GC도 증가했구요.

데이터의 크기로 보아 오히려 Executor의 수를 증가시킬 시 오버헤드가 발생 해 Task Time에 영향을 주고 있습니다.

분류 Case 3
Driver Memory 2G
Executor Cores 1
Executor Memory 2G
Num Executor 2
Driver Task Time 54s
Executor Task Time 30s

분류 Case 1 Case 2 Case 3
Driver Memory 2G 2G 2G
Executor Cores 4 1 1
Executor Memory 9 ~ 9.5G 2G 2G
Num Executor 1 1 2
Driver Task Time 45s 45s 54s
Executor Task Time 58s 24s 30s

실험 결과 이와 같은 지표로 나타났습니다.