이 문서에서는 대규모 일괄 파이프라인에서 작업 실패 영향을 최소화하는 방법을 설명합니다. 대규모 워크로드 실패는 복구하고 수정하는 데 드는 시간과 비용 때문에 특히 영향력이 큽니다. 이러한 파이프라인이 실패하여 파이프라인을 처음부터 재시도하면 시간과 비용이 많이 소요됩니다.
비용이 많이 드는 일괄 파이프라인 실패를 줄이려면 이 페이지의 가이드라인을 따르세요. 실패한 요소와 파이프라인 실패를 항상 완벽하게 방지할 수 없으므로 제공된 기법은 복원력 향상, 실패 비용 감소, 실패 발생 시 실패를 더욱 쉽게 디버그하고 이해하는 방법에 중점을 둡니다.
일반적인 파이프라인 권장사항은 Dataflow 파이프라인 권장사항을 참조하세요.
대규모 작업을 위해 소규모 실험 실행
대규모 일괄 작업을 실행하기 전에 데이터 세트 하위 집합에서 소규모 작업을 하나 이상 실행합니다. 이 기법은 예상 비용을 파악하고 잠재적인 장애점을 찾는 데 모두 도움이 될 수 있습니다.
예상 비용
실험을 실행하면 총 작업 실행 비용에 대한 예상 하한을 파악할 수 있습니다. 일반적으로 작업 비용 계산식은 cost of test job*size(full dataset)/size(test dataset)
입니다. 파이프라인에 따라 비용이 초선형으로 확장되거나 드물게 선형으로 확장될 수 있습니다. 하지만 이 단계를 통해 작업 비용을 대략적으로 예측할 수 있습니다. 다양한 입력 크기를 시도하여 비용이 확장되는 방식을 더 정확하게 예측할 수도 있습니다. 이 정보를 사용하여 기존 파이프라인을 계속 진행할지 아니면 비용을 절감하기 위해 파이프라인을 재구성할지 결정합니다.
장애점 찾기
실험을 실행하면 버그, 잠재적 장애점 또는 잠재적 구성 및 효율 문제가 노출될 수 있습니다. 다음 측정항목과 같은 다른 파이프라인 측정항목도 검사할 수 있습니다.
- 파이프라인에서 사용 가능한 메모리를 거의 다 사용한 경우 부하가 높거나 레코드가 매우 크면 메모리 부족(OOM) 예외가 발생할 수 있습니다. 이러한 OOM 오류를 방지하려면 최종 작업에 더 많은 메모리를 프로비저닝해야 할 수 있습니다.
- 파이프라인 처리량이 감소하면 파이프라인 로그를 검사하여 원인을 파악합니다. 중단된 요소나 특히 성능이 좋지 않은 데이터 세트 부분을 발견할 수 있습니다. 이러한 데이터 포인트를 별도로 처리하거나 요소를 처리할 때 제한 시간을 적용할 수 있습니다. 자세한 내용은 이 문서의 비용이 많이 드는 레코드에 제한 시간 적용 섹션을 참조하세요.
- Dataflow 태스크에서의 파이프라인 성능이 로컬에서보다 훨씬 더 나쁘면 파이프라인 로직을 검사하여 그 원인을 파악합니다. 예를 들어 Dataflow에서 코어 8개를 사용할 때와 로컬에서 코어 1개를 사용할 때의 처리량이 같으면 리소스 경합으로 인해 작업에서 병목 현상이 발생한 것일 수 있습니다. 성능이 예상보다 좋지 않으면 다음 옵션 중 하나 이상을 사용하는 것이 좋습니다.
- 다양한 머신 또는 소프트웨어 구성으로 실험을 더 많이 실행합니다.
- 로컬에서 코어 여러 개를 동시에 사용하여 테스트합니다.
- 코드를 검사하여 대규모로 배포할 때 발생할 수 있는 병목 현상을 찾습니다.
파이프라인에 Dataflow 권장사항이 있으면 이를 따라 성능을 개선합니다.
데드 레터 큐를 사용하여 예기치 못한 잘못된 데이터 처리
파이프라인은 대부분의 입력 요소에서 성공하지만 입력 하위 집합 일부에서는 실패하는 경우가 많습니다. 소규모 실험을 실행할 때는 입력 하위 집합만 테스트하므로 이 문제가 발견되지 않을 수 있습니다. 기본적으로 Dataflow는 이러한 실패한 태스크를 일괄 모드에서는 4번, 스트리밍 모드에서는 무제한으로 재시도합니다. 일괄 모드에서는 재시도 한도에 도달하면 전체 작업이 실패합니다. 스트리밍 모드에서는 무기한으로 정지될 수 있습니다.
많은 작업에서 이러한 실패 요소를 파이프라인에서 제외하고 데드 레터 큐(처리되지 않은 메시지 큐)를 사용하여 나머지 작업을 완료할 수 있습니다. 데드 레터 큐는 실패한 레코드를 별도의 출력 PCollection
에 전달하며 이 출력은 기본 출력과 별도로 관리될 수 있습니다. 이 구성을 사용하면 이러한 레코드에 대한 정책을 설계할 수 있습니다. 예를 들어 레코드를 Pub/Sub에 수동으로 작성하고 검사 및 정리한 후 레코드를 다시 처리할 수 있습니다.
많은 Apache Beam 변환에서 데드 레터 큐에 대한 지원을 기본 제공합니다. Java에서는 ErrorHandler
객체를 사용하여 액세스할 수 있습니다. Python에서는 with_exception_handling
메서드를 사용하여 액세스할 수 있습니다. 일부 변환에는 데드 레터 큐를 정의하는 커스텀 방법이 있으며 변환 문서에서 이 방법을 확인할 수 있습니다. 자세한 내용은 오류 처리에 데드 레터 큐 사용을 참조하세요.
작업이 데드 레터 큐의 기준을 충족하는지 확인하려면 이 문서의 제한사항 섹션을 참조하세요.
데드 레터 큐 제한사항
다음과 같은 경우에는 데드 레터 큐가 도움이 되지 않을 수 있습니다.
- 전체 작업자 또는
DoFn
수명주기 실패. 전체 작업자나 번들의 처리가 실패하면 데드 레터 큐에서 실패를 포착할 수 없습니다. 예를 들어 파이프라인에 메모리 부족(OOM) 예외가 발생하면 VM의 모든 활성 태스크가 실패하고 재시도되며 데드 레터 큐에는 아무것도 전송되지 않습니다. - 결합 또는 기타 집계. 파이프라인에서 모든 입력 요소가 결과의 일부로 존재하고 처리되어야 하는 계산을 실행하는 경우 이 단계 전에 데드 레터 큐를 사용할 때 주의해야 합니다. 데드 레터 큐를 사용하면 입력 데이터 일부가 결과에서 제외됩니다. 데드 레터 큐를 추가하면 내결함성을 얻는 대신 정확성이 저하될 수 있습니다.
- 데드 레터 큐 경로에서 실패. 요소가 데드 레터 큐 싱크로 전송되는 동안 실패하면 전체 파이프라인이 실패할 수 있습니다. 이러한 실패를 방지하려면 데드 레터 큐 로직을 최대한 기본적으로 유지합니다. 대기 단계(
wait class
참조)를 추가하여 데드 레터 큐 요소를 쓰기 전에 기본 입력이 완료되도록 할 수 있습니다. 이 구성은 성능을 저하시키고 파이프라인의 오류 신호를 지연시킬 수 있습니다. - 부분적으로 변환된 요소. 파이프라인 중간에 데드 레터 큐를 삽입하면 데드 레터 큐가 부분적으로 변환된 요소를 출력하고 원래 요소에 액세스하지 못할 수 있습니다. 따라서 요소를 정리하고 요소에 대해 파이프라인을 다시 실행할 수 없습니다. 대신 데드 레터 큐의 출력을 원래 요소와 상호 연결하는 다른 로직을 적용하거나 부분적으로 변환된 요소를 해석하고 처리해야 할 수 있습니다. 또한 일관되지 않은 결과가 발생할 수 있습니다. 예를 들어 요소가 파이프라인의 두 브랜치를 통해 전송되고 각 브랜치에서 예외를 발생시키는 요소를 데드 레터 큐로 보내는 경우 단일 입력 요소가 한 브랜치, 다른 브랜치, 두 브랜치 모두를 통해 전송되거나 어느 브랜치를 통해서도 전송되지 않을 수 있습니다.
비용이 많이 드는 레코드에 제한 시간 적용
비용이 더 많이 들거나 교착 상태와 같이 무응답의 원인이 되는 제한에 도달한 소수의 요소 하위 집합을 처리하는 동안 파이프라인에서 응답을 중지할 수 있습니다. 이 문제를 완화하기 위해 일부 변환에서는 제한 시간을 설정하고 이 문제가 발생한 사용자 코드 DoFn
에서 타임아웃된 요소를 실패하도록 허용합니다. 예를 들어 Python의 with_exception_handling
메서드를 사용할 수 있습니다. 데드 레터 큐와 제한 시간을 함께 사용하면 파이프라인에서 정상 요소를 계속 처리하고 진행할 수 있으며 개발자가 비용이 많이 드는 요소를 별도로 다시 처리할 수 있습니다. 이 구성으로 인해 성능 비용이 발생할 수 있습니다.
제한 시간이 필요한 DoFn
작업을 확인하려면 전체 파이프라인을 실행하기 전에 소규모 실험을 실행하세요.
수직 자동 확장 사용 설정
작업에 필요한 메모리 양을 잘 모르거나 작업이 메모리 부족 위험에 노출됐다고 생각되면 수직 자동 확장을 사용 설정하세요. 이 기능은 파이프라인이 대규모로 실행되거나 매우 큰 요소가 있을 때 OOM 실패를 방지하는 데 도움이 됩니다.
수직 자동 확장은 작업 비용을 늘릴 수 있으며 모든 메모리 부족 문제를 방지할 수 없으므로 개발자가 과도한 메모리 소비 문제를 해결해야 합니다. 수직 자동 확장을 사용하려면 Dataflow Prime도 필요하며 여기에는 추가 제한사항과 다른 결제 모델이 적용됩니다.
오류가 발생하기 쉬운 파이프라인 해결 방법
일부 파이프라인에서 오류가 특히 발생하기 쉽습니다. 이러한 오류의 근본 원인을 해결하는 것이 가장 좋지만 실패로 인한 비용을 줄이려면 다음 옵션을 사용하는 것이 좋습니다.
중간 결과 구체화
파이프라인에는 파이프라인 실행 시간을 좌우하는 특히 비용이 많이 드는 변환이 하나 이상 있을 수 있습니다. 이 변환 후에 파이프라인이 실패하면 이미 완료된 모든 작업이 손실되므로 특히 위험할 수 있습니다. 이 시나리오를 방지하려면 비용이 많이 드는 단계에서 생성된 중간 PCollections
를 Cloud Storage와 같은 싱크에 쓰는 것이 좋습니다. 이 구성은 실패 비용을 줄입니다. 이러한 이점과 추가 쓰기 수행 비용을 비교해야 합니다. 다음 방법 중 하나로 이 구체화된 결과를 사용할 수 있습니다.
- 원래 파이프라인을 중간 결과를 쓰는 파이프라인 하나와 읽는 파이프라인 하나 등 총 2개로 분할합니다.
- 파이프라인이 실패한 경우에만 원래 소스와 구체화된 중간 모음 모두에서 결과를 읽고 평면화합니다.
이러한 구체화가 추가 처리 전에 작성되게 하려면 후속 처리 단계 전에 대기 단계(wait class
참조)를 추가합니다.