18.5 디버깅 및 스파크 응급 처치
<스파크 애플리케이션이 시작되지 않는 경우>
클러스터나 사용자 애플리케이션 실행에 필요한 자원을 적절하게 설정하지 않았을 때 발생
증상
: 스파크 잡이 시작X
: 클러스터의 노드 정보를 표시X
: 스파크 UI가 잘못된 정보를 표시
대응법
-> 스파크 자원 설정이 올바른지, 클러스터 매니저가 스파크를 실행할 수 있도록 적합하게 설정되었는지 확인
-> 클러스터 매니저가 제공할 수 있는 메모리 자원 이상으로 익스큐터의 메모리 자원을 요청하는 경우 => 클러스터 매니저의 UI로 유휴 자원을 확인한 다음 할당할 메모리를 설정한다.
-> 설정한 포트로 클러스터 머신 간에 통신할 수 있는지 확인
<스파크 애플리케이션 실행 전에 오류가 발생한 경우>
증상
: 명령이 전혀 실행되지 않으며 오류 메시지가 출력
: 스파크 UI에서 잡, 스테이지, 태스크의 정보를 확인X
대응법
: 스파크 UI의 Environment 탭에서 애플리케이션 정보가 올바른지 확인한 다음 코드를 검토한다.
: 단순한 오타나 잘못된 컬럼명을 사용하는 경우가 많으며 스파크 실행 계획을 만드는 과정에서 오류가 발생한다.
: 클러스터의 드라이버, 워커, 사용하는 저장소 시스템 간의 네트워크 연결 상태를 다시 한번 확인한다.
: 라이브러리나 클래스패스를 확인
<스파크 애플리케이션 실행 중에 오류가 발생한 경우>
증상
: 하나의 스파크 잡이 전체 클러스터에서 성공적으로 실행되지만 다음 잡은 실패
: 쿼리의 특정 단계가 실패
: 오류 메시지를 해석하기 어렵다.
대응법
: 데이터가 존재하는지 또는 데이터가 올바른 포맷인지 확인한다.
: 잡의 태스크가 잠시 실행되다가 비정상적으로 종료된다면 입력 데이터 자체의 문제일 수 있다.
<느리거나 뒤처진 태스크>
애플리케이션을 최적화할 때 매우 흔하게 발생한다.
머신 간의 작업이 균등하게 분배되지 않거나 특정 머신이 다른 머신에 비해 처리 속도가 느린 경우에도 발생한다.
대응법
: 파티션별 데이터양을 줄이기 위해 파티션 수를 증가시킨다.
: 다른 컬럼을 조합해 파티션을 재분배한다.
: 가능하면 익스큐터의 메모리를 증가시킨다.
: 클러스터에 비정상적인 익스큐터나 머신이 있는지 확인한다.
<느린 집계 속도>
증상
: groupBy 호출 시 느린 태스크가 발생
: 집계 처리 이후의 잡이 느리다.
대응법
: 집계 연산 전에 파티션 수를 증가시키면 태스크별로 처리할 키 수를 줄일 수 있다.
: 집계 처리가 끝나고 이어서 실행되는 태스크가 느리다면 집계 처리된 데이터셋에 불균형 현상이 남아 있음을 의미한다. 이 경우 파티션을 임의로 재분배할 수 있도록 repartition 명령을 추가한다.
: null 값을 제어하기 위해 “ “ 또는 “EMPTY” 같은 값을 대체 값으로 사용하는지 확인한다.
: 성능이 중요한 경우 태생적으로 느린 함수는 사용을 피한다.
<느린 조인 속도>
증상
: 조인 스테이지의 처리 시간이 오래 걸린다.
: 조인 전후의 스테이지는 정상적으로 동작
대응법
: 다른 조인 타입을 변경한다.
: 조인 순서를 변경해본다.
: 조인을 수행하기 전에 데이터셋을 분할하여 클러스터 노드 간 데이터 이동을 줄인다.
: 스파크 애플리케이션이나 익스큐터의 자원 할당량을 늘리는 것이 도움이 될 수 있다.
: 필요한 데이터만 이용해서 조인 연산을 수행한다.
: null 값을 제어하기 위해 “ “ 또는 “EMPTY” 같은 값을 대체 값으로 사용하는지 확인한다.
<느린 읽기와 쓰기 속도>
증상
: 분산 파일 시스템이나 외부 시스템의 데이터를 읽는 속도가 느리다.
: 네트워크 파일 시스템이나 blob 저장소에 데이터를 쓰는 속도가 느리다.
대응법
: spark.speculation 속성을 true로 설정하면 느린 읽기와 쓰기 속도를 개선하는 데 도움이 될 수 있다.
(이 기능은 첫 번째 태스크에서 발생한 문제가 일시적인지 확인하기 위해 동일한 연산을 수행하는 태스크를 추가로 실행한다.)
: 단일 클러스터에서 스파크와 HDFS 같은 분산 파일 시스템을 함께 구성하려면 클러스터의 노드마다 스파크와 분산 파일 시스템 모두 동일한 호스트명을 인식하는지 확인한다.
<드라이버 OutOfMemoryError 또는 응답 없음>
: 스파크 애플리케이션이 비정상적으로 종료되므로 매우 심각한 문제
: 드라이버에 너무 많은 데이터를 전송해 메모리를 모두 소비한 경우에 자주 발생
증상
: 명령이 장시간 실행되거나 실행되지 않는다.
: 드라이버 JVM의 메모리 사용량이 많다.
대응법
: 스파크의 최대 브로드캐스트 조인 설정을 이용해 브로드캐스트할 크기를 제어할 수 있다.
: 자바 jmap 도구를 사용해서 힙 메모리의 히스토그램을 확인하여 드라이버 JVM의 메모리를 가장 많이 차지하는 객체를 찾는다.
: 드라이버의 가용 메모리를 증가시킨다.
: 파이썬을 사용하는 경우 JVM 메모리 부족 현상이 발생할 수 있다. 따라서 어떤 언어로 인해 발생했는지 확인
: SQL JDBC 서버와 노트북 환경을 이용해 다른 사용자와 SparkContext를 공유하는 상황이라면 여러 사용자가 동시에 대량의 데이터를 드라이버 메모리로 전송할 수 있는 명령을 실행하지 못하도록 막아야 한다.
<익스큐터 OutOfMemoryError 또는 응답 없음>
증상
: 익스큐터 로그에 OutOfMemoryError 또는 가비지 컬렉션과 관련된 메시지가 출력된다.
: 익스큐터가 비정상적으로 종료되거나 응답하지 않는다.
: 특정 노드의 느린 태스크가 복구되지 않는다.
대응법
: 익스큐터의 가용 메모리와 익스큐터 수를 증가
: PySpark 워커의 크기를 증가시킨다.
: 모든 익스큐터에 동일한 양의 작업이 할당되었는지 확인
: null 값을 정확하게 제어하기 위해 “ “ 또는 “EMPTY” 같은 값을 기본값으로 사용하는 것은 아닌지 확인한다.
: 가능하면 사용자 정의 함수의 사용을 줄이고 스파크의 구조적 API를 더 많이 사용해야 한다.
: 가장 많은 메모리를 사용하는 클래스를 확인한다.
: 키-값 저장소 같이 다른 워크로드를 처리하는 노드에 익스큐터가 위치한다면 스파크 잡을 다른 작업과 분리
<의도하지 않은 null 값이 있는 결과 데이터>
증상
: 트랜스포메이션이 실행된 결과에 의도치 않은 null 값이 발생
: 잘 동작하던 운영 환경의 스케줄 작업이 더 이상 동작하지 않거나 정확한 결과를 생성하지 못한다.
대응법
: 트랜스포메이션이 실제 유효한 쿼리 실행 계획을 생성하는지 확인한다.
: 중간 데이터셋이 의도한 대로 만들어졌는지 확인하고 최종 쿼리 실행 계획에 있는 모든 CAST 연산을 찾아 확인
<디스크 공간 없음 오류>
증상
: ‘no space left on disk’ 오류 메시지와 함께 잡이 실패
대응법
: 작업 노드의 디스크를 늘리거나 클라우드 환경의 외부 저장소를 추가해 디스크 공간을 확보한다.
: 제한된 용량의 저장소를 가진 클러스터를 사용하는 경우 데이터 치우침 현상이 발생하면 일부 노드의 저장소 공간이 꽉 찰 수 있기 때문에 데이터 파티션을 재분배하는 것이 좋다.
: 문제가 되는 머신의 오래된 로그 파일과 셔플 파일을 수동으로 제거한다.
<직렬화 오류>
증상
: 직렬화 오류와 함께 잡이 실패한다.
: UDF나 RDD를 이용해 개발된 사용자 정의 로직을 수행하는 익스큐터에서 직렬화 오류가 발생. 또한 이러한 익스큐터로 직렬화를 시도하는 태스크나 공유하려는 데이터를 직렬화할 수 없는 경우에 발생
대응법
: UDF나 함수로 직렬화 할 수 없는 코드 또는 데이터를 다루거나 직렬화 할 수 없는 이상한 데이터 타입을 다루는 경우에 직렬화 문제가 주로 발생하기 때문에 문제가 발생하면 직렬화 대상 사용자 클래스를 실제로 등록해 직렬화 성공 여부를 확인해야 한다.