Azure Event Hubs 이벤트 프로세서 문제 해결
이 문서에서는 형식을 사용할 EventProcessorClient
때 발생할 수 있는 일반적인 문제에 대한 솔루션을 제공합니다. Azure Event Hubs를 사용할 때 발생할 수 있는 다른 일반적인 문제에 대한 솔루션을 찾고 있는 경우 Azure Event Hubs 문제 해결을 참조 하세요.
이벤트 프로세서를 사용할 때 412 사전 조건 실패
클라이언트가 파티션의 소유권을 가져오거나 갱신하려고 하지만 소유권 레코드의 로컬 버전이 오래된 경우 412 사전 조건 오류가 발생합니다. 이 문제는 다른 프로세서 인스턴스가 파티션 소유권을 도용할 때 발생합니다. 자세한 내용은 다음 섹션을 참조하세요.
파티션 소유권이 자주 변경됩니다.
인스턴스 수가 EventProcessorClient
변경되면(즉, 추가되거나 제거됨) 실행 중인 인스턴스는 자체 간에 파티션 부하를 분산하려고 합니다. 프로세서 수가 변경된 후 몇 분 동안 파티션은 소유자를 변경해야 합니다. 분산된 후에는 파티션 소유권이 안정되고 자주 변경되지 않아야 합니다. 프로세서 수가 일정할 때 파티션 소유권이 자주 변경되는 경우 문제가 발생할 수 있습니다. 로그 및 재현과 함께 GitHub 문제를 제출하는 것이 좋습니다.
파티션 소유권은 .의 소유권 레코드를 CheckpointStore
통해 결정됩니다. 모든 부하 분산 간격에서 EventProcessorClient
다음 작업을 수행합니다.
- 최신 소유권 레코드를 가져옵니다.
- 레코드를 확인하여 파티션 소유권 만료 간격 내에서 타임스탬프를 업데이트하지 않은 레코드를 확인합니다. 이 조건과 일치하는 레코드만 고려됩니다.
- 소유되지 않은 파티션이 있고 부하가 인스턴스
EventProcessorClient
간에 분산되지 않는 경우 이벤트 프로세서 클라이언트는 파티션을 클레임하려고 합니다. - 해당 파티션에 대한 활성 링크가 있는 소유 파티션의 소유권 레코드를 업데이트합니다.
다음 목록에 설명된 대로 다음을 통해 EventProcessorClientBuilder
만들 EventProcessorClient
때 부하 분산 및 소유권 만료 간격을 구성할 수 있습니다.
- loadBalancingUpdateInterval(Duration) 메서드는 부하 분산 주기가 실행되는 빈도를 나타냅니다.
- partitionOwnershipExpirationInterval(Duration) 메서드는 프로세서가 파티션을 소유하지 않은 것으로 간주하기 전에 소유권 레코드가 업데이트된 이후의 최소 시간을 나타냅니다.
예를 들어 소유권 레코드가 오전 9시 30분에 업데이트되고 partitionOwnershipExpirationInterval
2분인 경우입니다. 부하 분산 주기가 발생하고 소유권 레코드가 지난 2분 또는 오전 9시 32분에 업데이트되지 않은 것으로 확인되면 파티션을 소유하지 않은 것으로 간주합니다.
파티션 소비자 중 하나에서 오류가 발생하면 해당 소비자를 닫지만 다음 부하 분산 주기까지 회수하려고 시도하지 않습니다.
"... epoch '0'이 있는 현재 수신기 '<RECEIVER_NAME>'의 연결이 끊어졌습니다."
전체 오류 메시지는 다음 출력과 유사합니다.
New receiver 'nil' with higher epoch of '0' is created hence current receiver 'nil' with epoch '0'
is getting disconnected. If you are recreating the receiver, make sure a higher epoch is used.
TrackingId:<GUID>, SystemTracker:<NAMESPACE>:eventhub:<EVENT_HUB_NAME>|<CONSUMER_GROUP>,
Timestamp:2022-01-01T12:00:00}"}
이 오류는 인스턴스를 추가하거나 제거한 후 EventProcessorClient
부하 분산이 발생할 때 발생합니다. 부하 분산은 진행 중인 프로세스입니다. 소비자와 함께 사용할 BlobCheckpointStore
경우 최대 30초마다(기본적으로) 소비자는 각 파티션에 대한 클레임이 있는 소비자를 확인하기 위해 검사 다음, 다른 소비자로부터 파티션을 '도용'해야 하는지 여부를 결정하는 몇 가지 논리를 실행합니다. 파티션에 대한 배타적 소유권을 어설션하는 데 사용되는 서비스 메커니즘을 Epoch라고 합니다.
그러나 추가되거나 제거되는 인스턴스가 없는 경우 해결해야 하는 기본 문제가 있습니다. 자세한 내용은 파티션 소유권 변경 빈도 섹션 및 GitHub 제출 문제를 참조하세요.
높은 CPU 사용량
높은 CPU 사용량은 일반적으로 인스턴스가 너무 많은 파티션을 소유하기 때문입니다. 모든 CPU 코어에 대해 3개 이하의 파티션을 사용하는 것이 좋습니다. 각 CPU 코어에 대해 1.5개의 파티션으로 시작한 다음 소유된 파티션 수를 늘려 테스트하는 것이 좋습니다.
메모리 부족 및 힙 크기 선택
JVM의 현재 최대 힙이 애플리케이션을 실행하기에 충분하지 않은 경우 OOM(메모리 부족) 문제가 발생할 수 있습니다. 애플리케이션의 힙 요구 사항을 측정할 수 있습니다. 그런 다음, 결과에 따라 JVM 옵션을 사용하여 적절한 최대 힙 메모리를 설정하여 힙의 -Xmx
크기를 조정합니다.
호스트(VM 또는 컨테이너)에 대해 사용 가능한 메모리 또는 제한 집합보다 큰 값으로 지정 -Xmx
해서는 안 됩니다(예: 컨테이너 구성에서 요청된 메모리). 호스트가 Java 힙을 지원하기에 충분한 메모리를 할당해야 합니다.
다음 단계에서는 최대 Java 힙의 값을 측정하는 일반적인 방법을 설명합니다.
프로덕션에 가까운 환경에서 애플리케이션을 실행합니다. 여기서 애플리케이션은 프로덕션에서 예상되는 최대 부하 하에서 이벤트를 보내고 받고 처리합니다.
애플리케이션이 안정적인 상태에 도달할 때까지 기다립니다. 이 단계에서 애플리케이션과 JVM은 모든 작업기본 개체, 클래스 형식, 정적 인스턴스, 개체 풀(TCP, DB 연결 풀) 등을 로드했습니다.
다음 스크린샷과 같이 안정적인 상태에서 힙 컬렉션에 대한 안정적인 톱니 모양의 패턴이 표시됩니다.
애플리케이션이 안정적인 상태에 도달하면 JConsole과 같은 도구를 사용하여 전체 GC(가비지 수집)를 강제로 적용합니다. 전체 GC 이후의 메모리를 관찰합니다. 전체 GC 후에 30%만 차지하도록 힙의 크기를 조정하려고 합니다. 이 값을 사용하여 최대 힙 크기(사용)를 설정할 수 있습니다
-Xmx
.
컨테이너에 있는 경우 JVM 인스턴스에 대한 비힙 요구 사항에 대해 최대 1GB의 메모리를 추가로 포함하도록 컨테이너 크기를 조정합니다.
프로세서 클라이언트 수신 중지
프로세서 클라이언트는 호스트 애플리케이션에서 며칠 동안 지속적으로 실행되는 경우가 많습니다. 경우에 따라 하나 이상의 파티션을 처리하지 않는 것을 EventProcessorClient
알 수 있습니다. 일반적으로 예외가 발생한 이유를 확인하기에 충분한 정보가 없습니다. EventProcessorClient
중지는 일시적인 오류에서 복구하는 동안 발생한 근본 원인(즉, 경합 상태)의 증상입니다. 필요한 정보는 GitHub 문제 제출을 참조하세요.
프로세서를 다시 시작할 때 받은 중복 EventData
EventProcessorClient
및 Event Hubs 서비스는 최소 한 번의 배달을 보장합니다. 메타데이터를 추가하여 중복 이벤트를 식별할 수 있습니다. 자세한 내용은 Stack Overflow에서 Azure Event Hubs가 한 번 이상 배달을 보장하나요? 한 번만 배달해야 하는 경우 클라이언트에서 승인을 기다리는 Service Bus를 고려해야 합니다. 메시징 서비스를 비교하려면 Azure 메시징 서비스 중에서 선택 항목을 참조 하세요.
레거시에서 새 클라이언트 라이브러리로 마이그레이션
마이그레이션 가이드에는 레거시 클라이언트에서 마이그레이션하고 레거시 검사포인트를 마이그레이션하는 단계가 포함되어 있습니다.
다음 단계
이 문서의 문제 해결 지침이 Java용 Azure SDK 클라이언트 라이브러리를 사용할 때 문제를 해결하는 데 도움이 되지 않는 경우 Java GitHub 리포지토리용 Azure SDK에 문제를 제출하는 것이 좋습니다.