Service Bus 메시징 예외(.NET)
Service Bus .NET 클라이언트 라이브러리는 서비스 작업 또는 클라이언트에서 오류가 발생할 때 예외를 표시합니다. 가능하면 표준 .NET 예외 형식을 사용하여 오류 정보를 전달합니다. Service Bus와 관련된 시나리오의 경우, ServiceBusException이 throw됩니다.
Service Bus 클라이언트는 구성된 재시도 옵션에 따라 일시적인 것으로 간주되는 예외를 자동으로 다시 시도합니다. 예외가 애플리케이션에 표시되면 모든 재시도가 실패로 적용되었거나 예외가 일시적이지 않은 것으로 간주되었습니다. 재시도 옵션 구성에 대한 자세한 내용은 재시도 옵션 사용자 지정 샘플에서 찾을 수 있습니다.
ServiceBusException
예외에는 오류의 컨텍스트 및 상대적 심각도를 이해하는 데 도움이 되는 몇 가지 컨텍스트 정보가 포함됩니다.
EntityPath
: 예외가 발생한 Service Bus 엔터티(사용 가능한 경우)를 식별합니다.IsTransient
: 예외가 복구 가능한 것으로 간주되는지 여부를 나타냅니다. 일시적인 것으로 간주되는 경우 Azure Service Bus는 이미 적절한 재시도 정책을 적용했으며 모든 재시도에 실패했습니다.Message
: 발생한 오류 및 관련 컨텍스트에 대한 설명을 제공합니다.StackTrace
: 호출 스택의 직접 프레임을 나타내며 오류가 발생한 코드의 위치를 강조 표시합니다.InnerException
: 서비스 작업의 결과로 예외가 발생한 경우 OASIS AMQP(Advanced Message Queuing Protocol) 1.0 사양에 따라 오류를 설명하는Microsoft.Azure.Amqp.AmqpException
인스턴스인 경우가 많습니다.Reason
: 근본 원인을 범주화하고 명확하게 설명하는 데 도움이 되는 잘 알려진 실패 이유를 제공합니다. 이러한 값은 예외 메시지의 텍스트를 검사하는 것이 적합하지 않는 경우 예외 필터링 및 기타 논리를 적용할 수 있도록 하기 위한 것입니다. 몇 가지 주요 실패 이유는 다음과 같습니다.ServiceTimeout
: Service Bus 서비스가 예상 시간 내에 작업 요청에 응답하지 않았음을 나타냅니다. 일시적인 네트워크 문제 또는 서비스 문제 때문일 수 있습니다. Service Bus 서비스가 요청을 성공적으로 완료했거나 완료하지 않았을 수 있습니다. 상태를 알 수 없습니다. 사용 가능한 다음 세션의 컨텍스트에서 이 예외는 엔터티에서 사용할 수 있는 잠금 해제된 세션이 없음을 나타냅니다. 이러한 오류는 자동으로 다시 시도되는 일시적인 오류입니다.QuotaExceeded
: 일반적으로 단일 엔터티에 대해 너무 많은 활성 수신 작업이 있음을 나타냅니다. 이 오류를 방지하려면 잠재적 동시 수신 수를 줄입니다. 일괄 처리 수신을 사용하여 수신 요청당 여러 메시지를 수신하려고 시도할 수 있습니다. 자세한 내용은 Service Bus 할당량을 참조하세요.MessageSizeExceeded
: 메시지 크기가 최대 메시지 크기를 초과했음을 나타냅니다. 메시지 크기에는 메시지 본문과 연결된 메타데이터가 포함됩니다. 이 오류를 해결하는 가장 좋은 방법은 일괄 처리로 전송되는 메시지의 수 또는 메시지에 포함된 본문의 크기를 줄이는 것입니다. 크기 제한은 변경될 수 있으므로 자세한 내용은 Service Bus 할당량을 참조하세요.MessageLockLost
: 메시지의 잠금이 손실되었음을 나타냅니다. 호출자는 메시지를 다시 받고 처리하려고 시도해야 합니다. 이 예외는 세션을 사용하지 않는 엔터티에만 적용됩니다. 이 오류는 처리가 잠금 기간보다 오래 걸리고 메시지 잠금이 갱신되지 않는 경우에 발생합니다. 일시적인 네트워크 문제로 인해 링크가 분리되거나 링크가 10분 동안 유휴 상태일 때도 이 오류가 발생할 수 있습니다.Service Bus 서비스는 상태 저장인 AMQP 프로토콜을 사용합니다. 프로토콜의 특성으로 인해 메시지를 받은 후 클라이언트와 서비스를 연결하는 링크는 분리되지만 메시지가 합의되기 전에 링크를 다시 연결할 때는 메시지를 합의할 수 없습니다. 링크가 분리되는 이유는 단기 일시적인 네트워크 오류나 네트워크 중단으로 인해 또는 서비스에 10분 유휴 시간 제한이 적용되는 경우입니다. 링크 재연결은 링크가 필요한 작업, 즉 메시지 합의 또는 수신의 일부로 자동으로 수행됩니다. 이 동작으로 인해 잠금 만료 시간이 아직 지나지 않았어도,
ServiceBusException
이MessageLockLost
또는SessionLockLost
의Reason
와 함께 발생할 수 있습니다.SessionLockLost
: 세션의 잠금이 만료되었음을 나타냅니다. 호출자는 세션을 다시 수락하려고 시도해야 합니다. 이 예외는 세션 사용 엔터티에만 적용됩니다. 이 오류는 처리가 잠금 기간보다 오래 걸리고 세션 잠금이 갱신되지 않는 경우에 발생합니다. 일시적인 네트워크 문제로 인해 링크가 분리되거나 링크가 10분 동안 유휴 상태일 때도 이 오류가 발생할 수 있습니다. Service Bus 서비스는 상태 저장인 AMQP 프로토콜을 사용합니다. 프로토콜의 특성으로 인해 메시지를 받은 후 클라이언트와 서비스를 연결하는 링크는 분리되지만 메시지가 합의되기 전에 링크를 다시 연결할 때는 메시지를 합의할 수 없습니다. 링크가 분리되는 이유는 단기 일시적인 네트워크 오류나 네트워크 중단으로 인해 또는 서비스에 10분 유휴 시간 제한이 적용되는 경우입니다. 링크 재연결은 링크가 필요한 작업, 즉 메시지 합의 또는 수신의 일부로 자동으로 수행됩니다. 이 동작으로 인해 잠금 만료 시간이 아직 지나지 않았어도,ServiceBusException
이MessageLockLost
또는SessionLockLost
의Reason
와 함께 발생할 수 있습니다.MessageNotFound
: 이 오류는 엔터티에 없거나 현재 잠겨 있는 메시지에 대해 시퀀스 번호로 지연된 메시지를 수신하려고 할 때 발생합니다.SessionCannotBeLocked
: 잠금이 이미 다른 위치에 있으므로 요청된 세션을 잠글 수 없음을 나타냅니다. 잠금이 만료되면 세션을 수락할 수 있습니다.GeneralError
: Service Bus 서비스에서 요청을 처리하는 중 오류가 발생했음을 나타냅니다. 이 오류는 종종 서비스 업그레이드 및 다시 시작으로 인해 발생합니다. 이러한 오류는 자동으로 다시 시도되는 일시적인 오류입니다.ServiceCommunicationProblem
: 서비스와 통신하는 중 오류가 발생했음을 나타냅니다. 이 문제는 일시적인 네트워크 문제 또는 서비스 문제에서 비롯되었을 수 있습니다. 이러한 오류는 자동으로 다시 시도될 일시적인 오류입니다.ServiceBusy
: 서비스에 의해 요청이 스로틀되었음을 나타냅니다. 요청을 스로틀할 수 있는 원인과 스로틀을 방지하는 방법을 설명하는 세부 정보는 여기에서 찾을 수 있습니다. 스로틀된 요청은 다시 시도되지만 클라이언트 라이브러리는 동일한ServiceBusClient
(또는 해당 클라이언트에서 만든 하위 형식)를 사용하여 더 많은 요청을 시도하기 전에 자동으로 10초 백오프를 적용합니다. 합의되지 않은 메시지 또는 잠긴 세션에 대해 메시지 또는 세션 잠금이 손실될 가능성이 있으므로 엔터티의 잠금 기간이 10초 미만인 경우 문제가 발생할 수 있습니다. 스로틀된 요청은 일반적으로 성공적으로 다시 시도되므로 생성된 예외는 오류가 아닌 경고로 기록됩니다. 특정 경고 수준 이벤트 원본 이벤트는 43입니다(RunOperation에서 예외가 발생했고 재시도가 발생함).MessagingEntityAlreadyExists
: 이름이 같은 엔터티가 동일한 네임스페이스 아래에 있음을 나타냅니다.MessagingEntityDisabled
: 메시징 엔터티가 사용 안 함으로 설정되었습니다. 포털을 사용하여 엔터티를 다시 사용하도록 설정합니다.MessagingEntityNotFound
: Service Bus 서비스에서 Service Bus 리소스를 찾을 수 없습니다.
ServiceBusException 처리 - 예제
다음은 ServiceBusException
을 처리하고 Reason
으로 필터링하는 방법을 보여주는 예입니다.
try
{
// Receive messages using the receiver client
}
catch (ServiceBusException ex) when
(ex.Reason == ServiceBusFailureReason.ServiceTimeout)
{
// Take action based on a service timeout
}
기타 일반적인 예외
ArgumentException
: 클라이언트는 클라이언트와 상호 작용할 때 제공된 매개 변수가 유효하지 않은 경우ArgumentException
에서 파생되는 이 예외를 throw합니다. 특정 매개 변수 및 문제의 특성에 대한 정보는Message
에서 찾을 수 있습니다.InvalidOperationException
: 현재 구성에 유효하지 않은 작업을 수행하려고 할 때 발생합니다. 이 예외는 일반적으로 클라이언트가 작업을 지원하도록 구성되지 않은 경우에 발생합니다. 클라이언트에 전달되는 옵션을 조정하여 완화할 수 있는 경우도 있습니다.NotSupportedException
: 요청된 작업이 클라이언트에 대해 유효하지만 현재 상태에서 지원되지 않는 경우에 발생합니다. 시나리오에 대한 정보는Message
에서 찾을 수 있습니다.AggregateException
: 작업에서 여러 예외가 발생할 수 있고 단일 실패로 표시될 때 발생합니다. 이 예외는 Service Bus 프로세서 또는 Service Bus 세션 프로세서를 시작하거나 중지할 때 가장 일반적으로 발생합니다.
이유: QuotaExceeded
이유가 QuotaExceeded
로 설정된 ServiceBusException은 특정 엔터티에 대한 할당량이 초과되었음을 나타냅니다.
참고 항목
Service Bus 할당량은 할당량을 참조하세요.
큐 및 토픽
큐 및 토픽의 경우 이는 큐의 크기인 경우가 많습니다. 다음 예제와 같이 오류 메시지 속성은 추가 세부 정보를 포함합니다.
Message: The maximum entity size has been reached or exceeded for Topic: 'xxx-xxx-xxx'.
Size of entity in bytes:1073742326, Max entity size in bytes:
1073741824..TrackingId:xxxxxxxxxxxxxxxxxxxxxxxxxx, TimeStamp:3/15/2013 7:50:18 AM
메시지는 토픽이 해당 크기 제한을 초과했음을 알려 줍니다. 이 경우 1GB입니다(기본 크기 제한).
네임스페이스
네임스페이스의 경우 QuotaExceeded 예외는 애플리케이션이 네임스페이스에 대한 최대 연결 수를 초과했음을 나타낼 수 있습니다. 예시:
<tracking-id-guid>_G12 --->
System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]:
ConnectionsQuotaExceeded for namespace xxx.
일반적인 원인
이 오류에 대한 두 가지 일반적인 원인은 배달 못 한 편지 큐와 정상적으로 작동하지 않는 메시지 수신기입니다.
배달 못 한 편지 큐 판독기는 메시지 완료에 실패하고 잠금이 만료되면 메시지는 큐/토픽으로 반환됩니다. 판독기에서 메시지 호출을 방지하는 예외가 발생하는 경우 발생할 수 있습니다. 메시지는 10번 읽혀진 후 기본적으로 배달 못 한 편지 큐로 이동합니다. 이 동작은 MaxDeliveryCount 속성에 의해 제어되고 기본값 10을 가집니다. 메시지는 배달 못 한 편지 큐에 쌓이고 공간을 차지합니다.
이 문제를 해결하려면 다른 큐에서와 마찬가지로 배달 못 한 편지 큐에서 메시지를 읽고 완료합니다.
수신기 중지됨. 수신기가 큐 또는 구독에서 메시지 수신을 중지했습니다. 문제를 식별하는 방법은 활성 메시지 수를 확인하는 것입니다. 활성 메시지 수가 높거나 증가하면 메시지는 작성되는 속도로 읽혀지지 않습니다.
이유: MessageLockLost
원인
이유가 MessageLockLost
로 설정된 ServiceBusException은 메시지가 PeekLock 수신 모드를 사용하여 수신되고 클라이언트에서 유지한 잠금은 서비스 측에서 만료됩니다.
메시지 잠금은 다양한 이유로 만료될 수 있습니다.
- 클라이언트 애플리케이션에서 갱신하기 전에 잠금 타이머가 만료되었습니다.
- 클라이언트 애플리케이션이 잠금을 확보하고 영구 저장소에 저장한 다음, 다시 시작되었습니다. 다시 시작된 후 클라이언트 애플리케이션이 Inflight 메시지를 검토하고 메시지를 완료하려고 시도했습니다.
다음 시나리오에서도 이 예외가 나타날 수 있습니다.
- 서비스 업데이트
- OS 업데이트
- 잠금을 보유하고 있는 동안 엔터티(큐, 토픽, 구독)의 속성 변경
해결
클라이언트 애플리케이션이 MessageLockLostException을 수신하면 더 이상 메시지를 처리할 수 없습니다. 클라이언트 애플리케이션은 필요에 따라 분석을 위해 예외를 로깅하는 것을 고려할 수 있지만 클라이언트는 메시지를 삭제해야 합니다.
메시지에 대한 잠금이 만료되었으므로 메시지가 큐(또는 구독)로 돌아가고 receive를 호출하는 다음 클라이언트 애플리케이션에 의해 처리될 수 있습니다.
MaxDeliveryCount가 초과되면 메시지가 DeadLetterQueue로 이동될 수 있습니다.
이유: SessionLockLost
원인
이유가 MessageLockLost
로 설정된 ServiceBusException은 세션이 수락되고 클라이언트에서 유지한 잠금이 서비스 쪽에서 만료될 때 throw됩니다.
세션 잠금은 다양한 이유로 만료될 수 있습니다.
- 클라이언트 애플리케이션에서 갱신하기 전에 잠금 타이머가 만료되었습니다.
- 클라이언트 애플리케이션이 잠금을 확보하고 영구 저장소에 저장한 다음, 다시 시작되었습니다. 다시 시작된 후 클라이언트 애플리케이션이 Inflight 세션을 검토하고 해당 세션에서 메시지를 처리하려고 했습니다.
다음 시나리오에서도 이 예외가 나타날 수 있습니다.
- 서비스 업데이트
- OS 업데이트
- 잠금을 보유하고 있는 동안 엔터티(큐, 토픽, 구독)의 속성 변경
해결
클라이언트 애플리케이션이 SessionLockLostException을 수신하면 더 이상 세션의 메시지를 처리할 수 없습니다. 클라이언트 애플리케이션은 분석을 위해 예외를 로깅하는 것을 고려할 수 있지만 클라이언트는 메시지를 삭제해야 합니다.
세션에 대한 잠금이 만료되었으므로 세션이 큐(또는 구독)로 돌아가고 세션을 호출하는 다음 클라이언트 애플리케이션에 의해 잠길 수 있습니다. 세션 잠금은 지정된 시간에 단일 클라이언트 애플리케이션이 확보하므로 순차적 처리가 보장됩니다.
TimeoutException
TimeoutException 은 사용자가 시작한 작업이 작업 시간 제한보다 더 오래 걸린다는 것을 나타냅니다.
이 제한에 도달하면 TimeoutException이 발생할 수 있으므로 ServicePointManager.DefaultConnectionLimit 속성 값도 확인해야 합니다.
서비스를 실행하는 리소스의 Service Bus 서비스 업데이트 또는 OS 업데이트와 같은 유지 관리 작업 도중 또는 작업 사이에 시간 제한이 발생할 것으로 예상됩니다. OS 업데이트 도중 엔터티가 이동하고 노드는 업데이트 또는 재부팅되며, 이로 인해 시간 제한이 발생할 수 있습니다. Azure Service Bus 서비스에 대한 SLA(서비스 수준 계약) 세부 정보는 Service Bus SLA를 참조하세요.
SocketException
원인
SocketException은 다음과 같은 경우에 throw됩니다.
- 지정된 시간(TCP 오류 코드 10060) 후에 호스트가 제대로 응답하지 않아서 연결 시도가 실패한 경우
- 연결된 호스트가 응답하지 못해 연결을 설정하지 못했습니다.
- 메시지를 처리하는 동안 오류가 발생했거나 원격 호스트가 시간 제한을 초과했습니다.
- 기본 네트워크 리소스 문제
해결
SocketException 오류는 애플리케이션을 호스트하는 VM이 <mynamespace>.servicebus.windows.net
이라는 이름을 해당 IP 주소로 변환할 수 없음을 의미합니다.
다음 명령이 IP 주소 매핑에 성공했는지 확인합니다.
PS C:\> nslookup <mynamespace>.servicebus.windows.net
다음과 같은 출력을 제공해야 합니다.
Name: <cloudappinstance>.cloudapp.net
Address: XX.XX.XXX.240
Aliases: <mynamespace>.servicebus.windows.net
위의 이름이 IP 및 네임스페이스 별칭으로 확인되지 않는 경우, 네트워크 관리자가 추가로 조사해야 할 사항을 확인합니다. 이름 확인은 일반적으로 고객 네트워크의 리소스인 DNS 서버를 통해 수행됩니다. Azure DNS에서 DNS 확인을 수행한 경우 Azure 지원에 문의하세요.
이름 확인이 예상대로 작동하는 경우 여기에서 Azure Service Bus에 대한 연결이 허용되는지 확인합니다.
UnauthorizedAccessException
UnauthorizedAccessException은 제공된 자격 증명이 요청된 작업을 수행할 수 없음을 나타냅니다. Message
속성에는 실패에 대한 세부 정보가 포함되어 있습니다.
ServiceBusClient
를 구성할 때 제공된 권한 부여 유형에 따라, 이러한 확인 단계를 따르는 것이 좋습니다.
지역에서 복제 예외
ServerBusyException
원인
- 비동기 복제(복제 지연 시간이 0보다 큰 경우) 클라이언트는 Service Bus 엔터티(큐, 토픽)에서 작업을 수행하거나 관리 작업을 수행하지만 주 지역과 보조 지역 간의 복제 지연 시간이 허용되는 최대 복제 지연 시간(초)을 초과했기 때문에 작업을 완료할 수 없습니다.
- 예: 새 복제 지연 시간이 설정된 최대 복제 지연 시간(300초)보다 큰 38,323초에 도달하므로 작업이 제한되고 있습니다. 복제되는 최신 작업의 현재 복제 지연 시간은 0초입니다.
- 엔터티에 대한 복제 큐가 최대 크기(바이트)를 초과합니다. 복제 큐의 최대 크기(바이트)는 Service Bus에서 설정한 내부 제한입니다.
- 예: 복제 큐 크기 73128000이 임계값 67108864 초과했습니다.
- 동기 복제에서는 다른 요청이 복제될 때까지 기다리는 동안 요청 시간이 초과됩니다.
- 예: skarri-storage-exp1(westus3)/q1:MessagingJournal에 대한 클라이언트 애플리케이션의 대량 요청입니다. 다른 지역에 대한 복제가 진행 중입니다.
해결
- 클라이언트는 서비스가 지정된 워크로드를 처리할 시간을 주기 위해 다시 해제해야 합니다. 그러면 클라이언트는 다시 시도해야 합니다.
시간 제한
원인
- Geo DR의 시간 제한 예외는 클라이언트가 제공한 시간 제한 내에서 작업이 완료되지 않았음을 의미합니다.
- 동기 복제에서 작업의 주 지역 쓰기 및 보조 지역에 대한 복제는 작업의 시간 제한 범위 내에 있습니다.
- 비동기 복제에서 작업의 주 지역 쓰기는 작업의 시간 제한 범위 내에 있지만 보조 지역에 대한 작업의 복제는 작업의 시간 제한 범위 내에 있지 않습니다.
- 예: 개체 메시지에 할당된 시간 00:01:00 내에 작업이 완료되지 않았습니다. (ServiceTimeout).
해결
- 클라이언트는 작업을 다시 시도해야 합니다.
- 시간 제한 작업의 일부 단계가 완료되었을 수 있습니다. 시간 제한 작업이 주 지역 및 일부 보조 지역에 기록되었을 수 있습니다. 작업이 주 지역에 기록된 경우 클라이언트 시간 제한에 관계없이 결국 모든 보조 지역에 복제됩니다.
BadRequest
원인
- 계획된 장애조치 동안 주 지역은 보조 지역이 따라잡을 수 있도록 일시적으로 읽기 전용으로 설정됩니다. 클라이언트가 이 임시 읽기 전용 상태인 동안 주 지역에 대한 쓰기 작업을 시도하는 경우 클라이언트는 BadRequest 예외를 받습니다.
- 예: 복제 역할 스위치가 진행 중이고, 주 복제본:<entity-name> 은 ReadOnly입니다.
해결
- 클라이언트는 쓰기 작업이 성공하기 전에 계획된 장애조치 완료되기를 기다려야 합니다.
- 계획된 장애조치 시간이 너무 오래 걸리는 경우 강제 장애 조치(failover)를 트리거할 수 있습니다.
다음 단계
전체 Service Bus .NET API 참조는 Azure .NET API 참조를 확인하세요. 문제 해결 팁은 문제 해결 가이드를 참조하세요.