대기 중인 메시지 문제 해결
이 섹션에는 WCF(Windows Communication Foundation)에서 큐를 사용하기 위한 일반적인 질문과 문제 해결 도움말이 포함되어 있습니다.
일반적인 질문
질문: WCF 베타 1을 사용하고 MSMQ 핫픽스를 설치했습니다. 핫픽스를 제거해야 합니까?
A: 예. 이 핫픽스는 더 이상 지원되지 않습니다. WCF를 이제 핫픽스 없이도 MSMQ에서 사용할 수 있습니다.
질문: MSMQ에 NetMsmqBinding 및 MsmqIntegrationBinding의 두 가지 바인딩이 있습니다. 어느 것을 언제 사용해야 합니까?
대답:NetMsmqBinding은 MSMQ를 사용하여 두 WCF 애플리케이션 사이에서 대기 중인 통신을 전송하려는 경우에 사용합니다. MsmqIntegrationBinding은 기존 MSMQ 애플리케이션을 사용하여 새 WCF 애플리케이션과 통신하려는 경우에 사용합니다.
질문:NetMsmqBinding 및 MsmqIntegration
바인딩을 사용하려면 MSMQ를 업그레이드해야 합니까?
A: 아니요. 두 바인딩 모두 Windows XP 및 Windows Server 2003의 MSMQ 3.0에서 작동합니다. 바인딩의 일부 기능은 Windows Vista에서 MSMQ 4.0으로 업그레이드하면 사용할 수 있게 됩니다.
질문:NetMsmqBinding 및 MsmqIntegrationBinding 바인딩의 기능 중 MSMQ 4.0에서는 사용할 수 있지만 MSMQ 3.0에서는 사용할 수 없는 것은 무엇입니까?
대답: 다음 기능은 MSMQ 4.0에서 사용할 수 있지만 MSMQ 3.0에서 사용할 수 없습니다.
사용자 지정 배달 못한 편지 큐는 MSMQ 4.0에서만 지원됩니다.
MSMQ 3.0과 4.0은 포이즌 메시지를 처리하는 방식이 다릅니다.
MSMQ 4.0에서만 트랜잭션된 원격 읽기를 지원합니다.
질문: 대기 중인 통신의 한쪽에서는 MSMQ 3.0을 사용하고 다른 쪽에서는 MSMQ 4.0을 사용할 수 있습니까?
A: 예.
질문: 기존 MSMQ 애플리케이션을 새 WCF 클라이언트 또는 서버와 통합하고 싶습니다. MSMQ 인프라의 양쪽을 모두 업그레이드해야 합니까?
A: 아니요. 어느 쪽에서도 MSMQ 4.0으로 업그레이드할 필요는 없습니다.
문제 해결
이 단원에는 일반적인 문제 해결 관련 질문의 답이 있습니다. 알려진 제한에 관한 몇 가지 문제는 릴리스 정보를 참조하십시오.
질문: 개인 큐를 사용하려고 하면 System.InvalidOperationException
예외 메시지가 표시됩니다. URL이 잘못되었습니다. 큐의 URL에는 '$' 문자가 포함될 수 없습니다. net.msmq://machine/private/queueName의 구문을 사용하여 개인 큐의 주소를 지정하십시오.
대답: 구성 및 코드에 있는 큐 URI(Uniform Resource Identifier)를 확인하세요. URI에는 "$" 문자를 사용하지 마십시오. 예를 들어 OrdersQueue라는 개인 큐를 지정하려면 URI를 net.msmq://localhost/private/ordersQueue
로 지정합니다.
질문: 대기 중인 애플리케이션에서 ServiceHost.Open()
을 호출하면 다음 예외가 throw됩니다. System.ArgumentException
: 기본 주소에는 URI 쿼리 문자열을 포함할 수 없습니다. 그 이유는
대답: 구성 및 코드에 있는 큐 URI를 확인하세요. MSMQ 큐에서는 '?' 문자 사용을 지원하지만 URI에서는 이 문자를 문자열 쿼리의 시작으로 해석합니다. 이 문제를 방지하려면 '?' 문자가 포함되지 않은 큐 이름을 사용합니다.
질문: 보내기에 성공했는데 수신기에서 서비스 작업이 호출되지 않습니다. 그 이유는
대답: 대답을 결정하려면 다음 검사 목록을 확인하세요.
트랜잭션 큐 요구 사항이 지정된 보증과 호환되는지 확인합니다. 다음 원칙에 주의하십시오.
"한 번만" 보증이(ExactlyOnce =
true
) 지정된 지속성 메시지(데이터그램 및 세션)는 트랜잭션 큐로만 보낼 수 있습니다."한 번만" 보증이 지정된 세션만 보낼 수 있습니다.
트랜잭션 큐의 세션에서 메시지를 받으려면 트랜잭션이 필요합니다.
보증이 없는(ExactlyOnce =
false
) 일시적 또는 지속성 메시지(데이터그램만 해당)는 비트랜잭션 큐로만 보내고 받을 수 있습니다.
배달 못한 편지 큐를 확인합니다. 거기에서 메시지를 찾은 경우에는 배달되지 않은 이유를 확인합니다.
보내는 큐에서 연결 또는 주소 지정 문제를 확인합니다.
질문: 사용자 지정 배달 못한 편지 큐를 지정했지만 송신 애플리케이션을 시작하면 배달 못한 편지 큐를 찾을 수 없거나 송신 애플리케이션에 배달 못한 편지 큐를 사용할 권한이 없다는 내용의 예외가 발생합니다. 이것이 발생하는 이유는?
대답: 사용자 지정 배달 못한 편지 큐 URI의 첫 세그먼트에 "localhost" 또는 net.msmq://localhost/private/myAppdead-letter queue와 같은 컴퓨터 이름이 포함되어 있어야 합니다.
질문: 항상 사용자 지정 배달 못한 편지 큐를 정의해야 합니까, 아니면 기본 배달 못한 편지 큐가 있습니까?
대답: 보증이 "한 번만"이고(ExactlyOnce = true
) 사용자 지정 배달 못한 편지 큐가 지정되지 않은 경우 기본값은 시스템 차원의 배달 못한 트랜잭션 큐입니다.
보증이 없는(ExactlyOnce = false
) 경우의 기본값은 배달 못한 편지 큐 기능을 사용하지 않는 것입니다.
질문: SvcHost.Open을 실행하면 서비스에서 "EndpointListener 요구 사항을 ListenerFactory에서 충족시킬 수 없습니다."라는 메시지와 함께 오류를 throw합니다. 그 이유는
A. 서비스 계약을 확인하십시오. 모든 서비스 작업에 "IsOneWay=true
"를 지정하는 것을 잊었을 수도 있습니다. 큐에서는 단방향 서비스 작업만 지원합니다.
질문: 큐에 메시지가 있지만 서비스 작업이 호출되지 않습니다. 문제가 무엇입니까?
대답: 서비스 호스트에 오류가 있는지 확인하세요. 추적을 검토하거나 IErrorHandler
를 구현하면 확인할 수 있습니다. 포이즌 메시지가 검색되면 기본적으로 서비스 호스트 오류가 발생합니다.
질문: 큐에 메시지가 있지만 대기 중인 웹 호스팅 서비스가 활성화되지 않습니다. 그 이유는
대답: 가장 일반적인 이유는 권한입니다.
NetMsmqActivator
프로세스가 실행되고 있으며NetMsmqActivator
프로세스의 ID에 큐에 대한 읽기 및 검색 권한이 있는지 확인하십시오.NetMsmqActivator
에서 원격 시스템에 있는 큐를 모니터링하는 경우에는NetMsmqActivator
가 제한된 토큰에서 실행되고 있지 않은지 확인합니다. 제한되지 않은 토큰으로NetMsmqActivator
를 실행하려면:sc sidtype NetMsmqActivator unrestricted
비보안 관련 웹 호스트 문제는 대기 중인 애플리케이션 웹 호스팅을 참조하세요.
질문: 세션에 가장 쉽게 액세스할 수 있는 방법은 무엇입니까?
대답: 세션의 마지막 메시지에 해당되는 작업에 AutoComplete=true
를 설정하고 모든 나머지 서비스 작업에 AutoComplete=false
를 설정합니다.
질문: 대기 중인 세션 메시지와 대기 중인 데이터그램 메시지를 모두 포함한 큐에서 읽는 경우 서비스에서 ProtocolException
을 throw하는 이유는 무엇입니까?
대답: 대기 중인 세션 메시지와 대기 중인 데이터그램 메시지의 작성 방식에는 근본적인 차이가 있습니다. 따라서 대기 중인 세션 메시지를 읽으려는 서비스에서 대기 중인 데이터그램 메시지를 받을 수 없고, 대기 중인 데이터그램 메시지를 읽으려는 서비스에서 대기 중인 세션 메시지를 받을 수 없습니다. 같은 큐에서 두 형식의 메시지를 모두 읽으려고 하면 다음 예외가 throw됩니다.
System.ServiceModel.MsmqPoisonMessageException: The transport channel detected a poison message. This occurred because the message exceeded the maximum number of delivery attempts or because the channel detected a fundamental problem with the message. The inner exception may contain additional information.
---> System.ServiceModel.ProtocolException: An incoming MSMQ message contained invalid or unexpected .NET Message Framing information in its body. The message cannot be received. Ensure that the sender is using a compatible service contract with a matching SessionMode.
애플리케이션에서 같은 컴퓨터로부터 대기 중인 세션 메시지와 대기 중인 데이터그램 메시지를 모두 보내는 경우, 사용자 지정 배달 못한 편지 큐와 시스템 배달 못한 편지 큐에서 특히 이 문제가 잘 발생합니다. 메시지를 보낼 수 없는 경우, 메시지는 배달 못한 편지 큐로 이동합니다. 이 경우 세션 메시지와 데이터그램 메시지가 모두 배달 못한 편지 큐에 들어갈 수 있습니다. 실행 중에 큐에서 읽는 동안 두 형식의 메시지를 구분할 방법이 없기 때문에, 애플리케이션에서 같은 컴퓨터로부터 대기 중인 세션 메시지와 대기 중인 데이터그램 메시지를 모두 보내면 안 됩니다.
MSMQ 통합: 특정 문제 해결
질문: 메시지를 보내거나 서비스 호스트를 열면 체계가 잘못되었음을 알리는 오류가 표시됩니다. 그 이유는
대답: MSMQ 통합 바인딩을 사용하는 경우에는 msmq.formatname 체계를 사용해야 합니다. 예를 들어 msmq.formatname:DIRECT=OS:.\private$\OrdersQueue입니다. 하지만 사용자 지정 배달 못한 편지 큐를 지정하는 경우에는 net.msmq 체계를 사용해야 합니다.
질문: 퍼블릭 또는 프라이빗 형식 이름을 사용하는 경우 Windows Vista에서 서비스 호스트를 열면 오류가 발생합니다. 그 이유는
대답: Windows Vista의 WCF 통합 채널은 포이즌 메시지 처리를 위해 주 애플리케이션 큐에 하위 큐를 열 수 있는지 확인합니다. 하위 큐의 이름은 수신기에 전달되는 msmq.formatname URI에서 파생됩니다. MSMQ에서 하위 큐 이름에는 직접 형식 이름만 사용할 수 있습니다. 따라서 오류가 발생합니다. 큐 URI를 직접 형식 이름으로 변경하십시오.
질문: MSMQ 애플리케이션에서 메시지를 받을 때 메시지가 큐에 들어간 후 수신 WCF 애플리케이션에 읽히지 않습니다. 그 이유는
대답: 메시지에 본문이 있는지 확인하세요. 메시지에 본문이 없으면 MSMQ 통합 채널에서 메시지를 무시합니다. 예외에 대한 알림을 받고 추적을 확인하려면 IErrorHandler
를 구현하십시오.
보안 관련 문제 해결
질문: 작업 그룹 모드에서 기본 바인딩을 사용하는 샘플을 실행하면 메시지가 보내지는 것 같지만 수신자에게 전달되지 않습니다.
대답: 기본적으로 메시지는 Active Directory 디렉터리 서비스가 필요한 MSMQ 내부 인증서를 사용하여 서명됩니다. 작업 그룹 모드에서는 Active Directory를 사용할 수 없기 때문에 메시지 서명이 실패합니다. 이에 따라 배달 못 한 편지 큐에 메시지가 삽입되고 "잘못된 서명" 등의 오류가 표시됩니다.
해결 방법은 보안을 해제하는 것입니다. 보안을 해제하려면 Mode = None으로 설정하여 작업 그룹 모드에서 작동하도록 합니다.
다른 해결 방법은 MsmqTransportSecurity를 Transport 속성에서 가져와서 Certificate로 설정하고 클라이언트 인증서를 설정하는 것입니다.
또 다른 해결 방법은 Active Directory 통합을 사용하는 MSMQ를 설치하는 것입니다.
질문: Active Directory에서 기본 바인딩(전송 보안 설정됨)을 통해 큐에 메시지를 보내면 "내부 인증서를 찾을 수 없다."는 메시지가 표시됩니다. 이 문제를 해결하려면 어떻게 해야 합니까?
대답: Active Directory에 있는 발신자 인증서를 갱신해야 합니다. 그러려면 제어판, 관리 도구, 컴퓨터 관리를 연 다음, MSMQ를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다. 사용자 인증서 탭을 선택하고 갱신 단추를 클릭합니다.
질문:Certificate를 사용하여 메시지를 보낼 때 사용할 인증서를 지정하면 "잘못된 인증서" 메시지가 표시됩니다. 이 문제를 해결하려면 어떻게 해야 합니까?
대답: 인증서 모드에서는 로컬 시스템 인증서 저장소를 사용할 수 없습니다. 인증서 스냅인을 사용하여 시스템 인증서 저장소에서 현재 사용자 저장소로 인증서를 복사해야 합니다. 인증서 스냅인을 가져오려면 다음을 수행하십시오.
시작을 클릭하고 실행을 선택한 다음,
mmc
를 입력하고 확인을 클릭합니다.Microsoft Management Console에서 파일 메뉴를 열고 스냅인 추가/제거를 선택합니다.
스냅인 추가/제거 대화 상자에서 추가 단추를 클릭합니다.
독립 실행형 스냅인 추가 대화 상자에서 인증서를 선택하고 추가를 클릭합니다.
인증서 스냅인 대화 상자에서 내 사용자 계정을 선택하고 마침을 클릭합니다.
다음으로 이전 단계를 사용해서 두 번째 인증서 스냅인을 추가하는데, 이번에는 컴퓨터 계정을 선택하고 다음을 클릭합니다.
로컬 컴퓨터를 선택하고 마침을 클릭합니다. 이제 시스템 인증서 저장소에서 현재 사용자 저장소로 인증서를 끌어서 놓을 수 있습니다.
질문: 서비스가 작업 그룹 모드에서 다른 컴퓨터에 있는 큐를 읽으면 "액세스 거부" 예외가 발생합니다.
대답: 작업 그룹 모드에서 원격 애플리케이션이 큐에 액세스하려면 애플리케이션에 큐 액세스 권한이 있어야 합니다. 큐의 ACL(액세스 제어 목록)에 "익명 로그인"을 추가하고 익명 로그인에 읽기 권한을 부여합니다.
질문: 네트워크 서비스 클라이언트 또는 도메인 계정이 없는 임의의 클라이언트에서 대기 중인 메시지를 보내면 잘못된 인증서라는 메시지가 표시되면서 보내기가 실패합니다. 이 문제를 해결하려면 어떻게 해야 합니까?
대답: 바인딩 구성을 확인합니다. 기본 바인딩에는 메시지 서명을 위해 MSMQ 전송 보안이 설정되어 있습니다. MSMQ 전송 보안을 해제하십시오.
트랜잭션된 원격 수신
질문: 시스템 A에 큐가 있고 시스템 B에 큐에서 메시지를 읽는 WCF 서비스가 있는데(트랜잭션된 원격 수신 시나리오) 큐에서 메시지를 읽을 수 없습니다. 추적 정보를 보면 "트랜잭션을 가져올 수 없다."는 메시지로 인해 수신이 실패했음을 확인할 수 있습니다. 이 문제를 해결하려면 어떻게 해야 합니까?
대답: 세 가지 원인이 있을 수 있습니다.
도메인 모드에 있는 경우 트랜잭션된 원격 수신을 수행하려면 MSDTC(Microsoft Distributed Transaction Coordinator) 네트워크 액세스가 필요합니다. 이 설정은 구성 요소 추가/제거를 사용하여 사용하도록 설정할 수 있습니다.
트랜잭션 관리자와의 통신을 위한 인증 모드를 확인합니다. 작업 그룹 모드에 있는 경우에는 "인증 필요 없음"을 선택해야 합니다. 도메인 모드에 있는 경우에는 "수동 인증 필요"를 선택해야 합니다.
인터넷 연결 방화벽 설정에서 예외 목록에 MSDTC가 있는지 확인하세요.
Windows Vista를 사용하고 있는지 확인합니다. Windows Vista의 MSMQ는 원격 트랜잭션 읽기를 지원합니다. 이전 Windows 릴리스의 MSMQ에서는 트랜잭션된 원격 읽기를 지원하지 않습니다.
질문: 큐에서 읽는 서비스가 네트워크 서비스인 경우 웹 호스트 등에서 큐에서 읽을 때 액세스 거부 예외가 발생하는 이유는 무엇입니까?
대답: 큐 ACL에 네트워크 서비스 읽기 권한을 추가해야 네트워크 서비스가 큐에서 읽을 수 있습니다.
질문: 원격 시스템의 큐에 있는 메시지를 기준으로 MSMQ 정품 인증 서비스를 사용하여 애플리케이션을 활성화할 수 있습니까?
A: 예. 이렇게 하려면 네트워크 서비스로 실행되도록 MSMQ 정품 인증 서비스를 구성하고 원격 시스템의 큐에 대한 네트워크 서비스 액세스 권한을 추가해야 합니다.
ReceiveContext를 사용하는 사용자 지정 MSMQ 바인딩 사용
ReceiveContext를 사용하는 사용자 지정 MSMQ 바인딩을 사용하는 경우 네이티브 MSMQ가 비동기 ReceiveContext에 대한 I/O 완료를 지원하지 않기 때문에 들어오는 메시지 처리에서 스레드 풀 스레드를 사용합니다. 이는 이러한 메시지 처리에서 ReceiveContext에 내부 트랜잭션을 사용하고 MSMQ가 비동기 처리를 지원하지 않기 때문입니다. 이 문제를 해결하려면 SynchronousReceiveBehavior를 엔드포인트에 추가하여 동기 처리를 강제로 수행하거나 MaxPendingReceives를 1로 설정하면 됩니다.