이 문서에서는 형식을 사용할 EventProcessorClient 때 발생할 수 있는 일반적인 문제에 대한 솔루션을 제공합니다. Azure Event Hubs를 사용할 때 발생할 수 있는 다른 일반적인 문제에 대한 솔루션을 찾고 있는 경우 Azure Event Hubs 문제 해결을 참조하세요.
이벤트 프로세서를 사용할 때 412 사전 조건 실패
클라이언트가 파티션의 소유권을 가져오거나 갱신하려고 하지만 소유권 레코드의 로컬 버전이 오래된 경우 412 사전 조건 오류가 발생합니다. 이 문제는 다른 프로세서 인스턴스가 파티션 소유권을 도용할 때 발생합니다. 자세한 내용은 다음 섹션을 참조하세요.
파티션 소유권이 자주 변경됩니다.
인스턴스 수가 EventProcessorClient 변경되면(즉, 추가되거나 제거됨) 실행 중인 인스턴스는 자체 간에 파티션 부하를 분산하려고 합니다. 프로세서 수가 변경된 후 몇 분 동안 파티션은 소유자를 변경해야 합니다. 균형이 잡힌 후에는 파티션 소유권이 안정적으로 유지되고 자주 변경되지 않아야 합니다. 프로세서 수가 일정할 때 파티션 소유권이 자주 변경되는 경우 문제가 발생할 수 있습니다. 로그 및 재현과 함께 GitHub 문제를 제출하는 것이 좋습니다.
파티션 소유권은 CheckpointStore에 있는 소유권 레코드를 통해 결정됩니다. 모든 부하 분산 간격에서 EventProcessorClient 다음 작업을 수행합니다.
- 최신 소유권 레코드를 가져옵니다.
- 레코드를 확인하여 파티션 소유권 만료 간격 내에서 타임스탬프를 업데이트하지 않은 레코드를 확인합니다. 이 조건과 일치하는 레코드만 고려됩니다.
- 소유되지 않은 파티션이 있고 부하가 인스턴스
EventProcessorClient간에 분산되지 않는 경우 이벤트 프로세서 클라이언트는 파티션을 클레임하려고 합니다. - 소유 중인 파티션 중 해당 파티션에 대한 활성 링크가 있는 것의 소유권 기록을 업데이트합니다.
EventProcessorClient를 통해 EventProcessorClientBuilder을(를) 만들 때, 다음 목록에 설명된 대로 부하 분산 및 소유권 만료 간격을 구성할 수 있습니다.
- 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 메시징 서비스 중에서 선택 항목을 참조하세요.
하위 수준 소비자 클라이언트 수신 중지
EventHubConsumerAsyncClient 는 Event Hubs 라이브러리에서 제공하는 하위 수준 소비자 클라이언트로, 반응형 애플리케이션을 보다 제어하고 유연하게 제어해야 하는 고급 사용자를 위해 설계되었습니다. 이 클라이언트는 사용자가 Reactor 체인 내에서 백프레서, 스레딩 및 복구를 관리할 수 있도록 하는 하위 수준 인터페이스를 제공합니다. 달리 EventProcessorClient, EventHubConsumerAsyncClient 모든 터미널 원인에 대한 자동 복구 메커니즘을 포함하지 않습니다. 따라서 사용자는 터미널 이벤트를 처리하고 적절한 Reactor 연산자를 선택하여 복구 전략을 구현해야 합니다.
이 메서드는 EventHubConsumerAsyncClient::receiveFromPartition 연결에서 다시 시도할 수 없는 오류가 발생하거나 일련의 연결 복구 시도가 연속적으로 실패하여 최대 재시도 한도가 소진될 때 터미널 오류를 내보낸다. 하위 수준 수신기는 일시적인 오류로부터 복구를 시도하지만 소비자 클라이언트 사용자는 터미널 이벤트를 처리해야 합니다. 연속 이벤트 수신이 필요한 경우 애플리케이션은 터미널 이벤트에서 새 소비자 클라이언트를 만들도록 Reactor 체인을 조정해야 합니다.
레거시에서 새 클라이언트 라이브러리로 마이그레이션
마이그레이션 가이드에는 레거시 클라이언트에서 마이그레이션하고 레거시 검사점을 마이그레이션하는 단계가 포함되어 있습니다.
다음 단계
문제 해결을 위한 이 문서의 지침이 Java용 Azure SDK 클라이언트 라이브러리에 대한 문제를 해결하는 데 도움이 되지 않는 경우, Azure SDK for Java GitHub 리포지토리