통신 개체 인 System.ServiceModel.Channels.ServiceChannel은 통신에 사용할 수 없습니다.


159

통신 개체 인 System.ServiceModel.Channels.ServiceChannel은 Faulted 상태이므로 통신에 사용할 수 없습니다.

이 오류는 무엇이며 어떻게 해결해야합니까?

답변:


152

이 오류는 서버 측에서 .NET 예외가 발생하도록했고이를 포착 및 처리하지 않았고이를 SOAP 오류로 변환하지 않았기 때문에 발생합니다.

이제 서버 측이 "폭발"했기 때문에 WCF 런타임이 채널을 "결함"했습니다. 예를 들어 클라이언트와 서버 간의 통신 링크를 사용할 수 없습니다. 결국 서버가 폭발 한 것처럼 보이므로 통신 할 수 없습니다. 더 이상.

따라서해야 할 일은 다음과 같습니다.

  • 항상 서버 측 오류를 포착하고 처리합니다. .NET 예외가 서버에서 클라이언트로 전달 되지 않도록하십시오. 항상 이러한 오류를 상호 운용 가능한 SOAP 오류로 래핑하십시오. WCF IErrorHandler 인터페이스를 확인 하고 서버 측에서 구현하십시오.

  • 클라이언트에서 채널로 두 번째 메시지를 보내려는 경우 채널이 오류 상태가 아닌지 확인합니다.

    if(client.InnerChannel.State != System.ServiceModel.CommunicationState.Faulted)
    {
       // call service - everything's fine
    }
    else
    {
       // channel faulted - re-create your client and then try again
    }
    

    만약 그렇다면, 당신이 할 수있는 일은 그것을 폐기하고 클라이언트 측 프록시를 다시 만든 다음 다시 시도하는 것입니다.


11
클라이언트 측에도 문제가있는 경우에도 동일한 오류가 발생할 수 있습니다. 예를 들어 수신 메시지에 대한 메시지 크기 할당량이 초과 된 경우입니다.
svick

6
클라이언트를 어떻게 다시 만들 수 있습니까?
Masoud

34

서버가 Fault 상태가되지 않도록하려면 처리되지 않은 예외가 발생하지 않도록해야합니다. WCF에 예기치 않은 예외가 표시되면 더 이상 호출이 허용되지 않습니다.
이 동작을 피할 수있는 두 가지 가능성 :

  1. 오류 예외를합니다 (WCF 서버가 여전히 유효한 상태를 가지고 있음을 알 수 있도록이 하나, WCF에 대한 예상치 못한 아닌)를 사용
    하는 대신

    throw new Exception("Error xy in my function")  
    

    항상 사용

    throw new FaultException("Error xy in my function")  
    

    아마도 당신은 .. 전체 블록을 잡아 내고 Exception의 모든 경우에 FaultException을 던질 수 있습니다.

    try   
    {  
        ... some code here   
    }
    catch (Exception ex)
    {  
        throw new FaultException(ex.Message)   
    }
    
  2. 오류 처리기를 사용하여 모든 예외를 처리하도록 WCF에 지시합니다. 이것은 여러 가지 방법으로 수행 할 수 있습니다. 속성을 사용하여 간단한 것을 선택했습니다.
    우리가해야 할 일은 [SvcErrorHandlerBehaviour]원하는 서비스 구현 에서 속성을 사용하는 것 입니다.

    using System;
    using System.Collections.ObjectModel;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
    
    namespace MainService.Services
    {
        /// <summary>
        /// Provides FaultExceptions for all Methods Calls of a Service that fails with an Exception
        /// </summary>
        public class SvcErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior
        {
            public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            { } //implementation not needed
    
            public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints,
                                             BindingParameterCollection bindingParameters)
            { } //implementation not needed
    
            public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            {
                foreach (ChannelDispatcherBase chanDispBase in serviceHostBase.ChannelDispatchers)
                {
                    ChannelDispatcher channelDispatcher = chanDispBase as ChannelDispatcher;
                    if (channelDispatcher == null)
                        continue;
                    channelDispatcher.ErrorHandlers.Add(new SvcErrorHandler());
                }
            }
        }
    
        public class SvcErrorHandler: IErrorHandler
        {
            public bool HandleError(Exception error)
            {
                //You can log th message if you want.
                return true;
            }
    
            public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
            {
                if (error is FaultException)
                    return;
    
                FaultException faultException = new FaultException(error.Message);
                MessageFault messageFault = faultException.CreateMessageFault();
                msg = Message.CreateMessage(version, messageFault, faultException.Action);
            }
        }
    }
    

이것은 쉬운 예입니다. naked을 사용하지 않고 IErrorhandler에 대해 더 자세히 알아볼 수 FaultException있지만 FaultException<>추가 정보를 제공하는 유형이 있는 경우 자세한 예는 IErrorHandler 를 참조하십시오 .


10

사실, marc_s의 제안을 따른 후에도 실패 할 경우 서버의 web.config에있는 서버 바인딩 구성 (또는 그 부족)의 <security> 요소로 인해이 예외가 발생할 수 있습니다. 예를 들어 서버는 Message수준의 보안을 예상 하고 클라이언트는 다음과 같이 구성됩니다 None(또는 서버가 Active Directory 도메인의 일부가 아니지만 원격 클라이언트 호스트가있는 경우).

팁 : 이러한 경우 클라이언트 앱은 RDP 세션의 관리 계정으로 서버 컴퓨터에서 직접 실행될 때 웹 서비스 벌금을 호출 할 가능성이 높습니다.


2

이 문제를 진단하려면 Visual Studio 디버거에서 서비스를 실행하십시오. Debug | Exceptions 메뉴를 사용하고 예외가 발생할 때 중단 할 것을 표시합니다.

throw 된 원래 예외는 "..it is in the Faulted"보다 훨씬 더 나은 오류 메시지를 갖습니다.

예를 들어 ServiceHost.Open ()에서이 예외가 발생했지만 발생했을 때 원래 예외가 발생했을 때 오류 메시지는 다음과 같습니다.

서비스 'MyServiceName'에는 애플리케이션 (비 인프라) 엔드 포인트가 없습니다. 이는 애플리케이션에 대한 구성 파일이 없거나 구성 파일에서 서비스 이름과 일치하는 서비스 요소를 찾을 수 없거나 서비스 요소에 엔드 포인트가 정의되지 않았기 때문일 수 있습니다.

App.config에서 맞춤법 오류를 수정하면 문제가 해결되었습니다.


VS2015에서 디버그 → 예외 설정을 선택하고 공용 언어 런타임 예외를 선택합니다.
SharpC

1
그렇다면 Visual Studio 디버거를 사용할 때까지 원래 예외가 주어지지 않은 이유는 무엇입니까?
Jez

2

http asmx 서비스에서 net.tcp wcf 서비스 끝점을 사용하는 동안 동일한 문제가 발생했습니다.

내가 본 것처럼 아무도이 문제가 발생하는 이유에 대한 구체적인 답변을 작성하지 않았지만 올바르게 처리하는 방법 만 작성했습니다.

나는 며칠 연속으로 어려움을 겪었고 마침내 내 경우 문제가 어디에서 오는지 알아 냈습니다.

처음에는 서비스에 대한 참조를 만들 때 구성 파일이 소스에있는 것과 동일한 방식으로 보안 태그에 대해 구성 될 것이라고 생각했지만, 그렇지 않았으므로 수동으로 처리해야합니다. 내 경우에는

<netTcpBinding>
    <binding name="NetTcpBinding_IAuthenticationLoggerService"
    </binding>
</netTcpBinding>`

나중에 보안 부분이없는 것을 보았습니다.

<netTcpBinding>
    <binding name="NetTcpBinding_IAuthenticationLoggerService" transferMode="Buffered">
      <security mode="None">
        <transport clientCredentialType="None"/>
      </security>
    </binding>
  </netTcpBinding>

내 경우 두 번째 문제는 transferMode="Streamed"소스 WCF 서비스에서 사용하고 있었고 클라이언트에서는 기본값 transferModeBuffered소스와 클라이언트 모두에서 동일하게 구성되는 것이 중요 하기 때문에 나쁘다. 방법.


1

다른 답변에서 언급되지 않은 다른 문제가 있습니다.

동일한 TCP 주소 및 포트에서 엔드 포인트를 서비스해야합니다. app.config에서 두 끝점을 모두 추가하는 것을 잊었으므로 서비스가 올바른 포트에서 실행되었지만 잘못된 서비스 인터페이스로 실행되었습니다.


1

Visual Studio의 디버그에이 메시지가 표시되고 솔루션에 WCF 프로젝트가 포함 된 경우. 그런 다음이 WCF 프로젝트 설정을 열고-> "WCF 옵션"탭으로 이동-> "디버깅 할 때 WCF 서비스 호스트 시작 ..."옵션을 끕니다.


나는 같은 문제가 있었고 꽤 오랫동안이 문제에 붙어있었습니다. 아마도 클라이언트와 서버를 동일한 솔루션에 두는 것은 좋은 습관이 아닙니다. 감사합니다!
yoosha jul.

1

저에게 문제는 WSDL을 가져 와서 자동으로 생성 된 구성 파일로 인해 발생했습니다. 바인딩을 basicHttpBinding에서 customBinding으로 업데이트했습니다. 추가 예외 처리를 추가해도이를 지적하는 데 도움이되지 않았습니다.

전에

<basicHttpBinding>
            <binding name="ServiceName">
                <security mode="Transport" />
            </binding>
        </basicHttpBinding>`

<customBinding>
        <binding name="ServiceName">
          <textMessageEncoding messageVersion="Soap12" />
          <httpsTransport />
        </binding>
      </customBinding>`

0

제 경우 이유는로드 할 수없는 잘못된 인증서였습니다. 시스템 아래의 이벤트 뷰어에서 발견했습니다.

TLS 서버 신임 개인 키에 액세스를 시도 할 때 치명적 오류가 발생했습니다. 암호화 모듈에서 반환 된 오류 코드는 0x8009030D입니다. 내부 오류 상태는 10001입니다.


0

이 오류는 처리되지 않은 예외뿐만 아니라 사용자 컴퓨터에서도 발생할 수 있습니다. 서버 / 컴퓨터의 시계 시간이 너무 많은 시간이 걸리면 많은 .NET 웹 서비스가 처리되지 않은 오류로 요청을 거부합니다. 그것은 그들의 관점에서 처리되지만 당신의 관점에서는 다루지 않습니다. 수신 서버의 시계 시간이 올바른지 확인하십시오. 수정해야하는 경우 채널을 다시 열기 전에 서비스를 재설정하거나 재부팅해야합니다.

방화벽이 인터넷 시간 업데이트를 차단 한 서버에서이 문제가 발생했으며 어떤 이유로 서버가 시간을 잃었습니다. 모든 타사 .NET 웹 서비스는 웹 서비스 요청을 거부했기 때문에 오류가 발생했습니다. 이벤트 뷰어를 살펴보면 문제를 식별하는 데 도움이되었지만 시계를 조정하면 문제가 해결되었습니다. 향후 웹 서비스 호출에 대해 Faulted State 오류 메시지를 받았음에도 불구하고 오류가 발생했습니다.


0

서버는 수신 시간 초과 ( 기본값 : 10 분 ) 동안 메시지가 수신되지 않은 연결을 자동으로 중단합니다 . 이것은 클라이언트가 서버가 무제한의 시간 동안 연결을 열도록 강제하는 것을 방지하기위한 DoS 완화입니다.

서버가 유휴 상태가되어 연결을 중단하므로 클라이언트는이 예외를받습니다.

서버의 바인딩에서 수신 시간 제한을 구성하여 서버가 연결을 중단하기 전에 유휴 상태가되도록 허용하는 시간을 제어 할 수 있습니다. 크레딧 : TRVishwanath-MSFT


0

나는 이것이 오래된 게시물이라는 것을 알고 있지만 보안을 변경할 수 없을 때주의해야 할 한 가지는 사용자 이름과 암호가 설정되어 있는지 확인하는 것입니다.

사용자 이름과 암호가 서비스 클라이언트에 대해 설정되지 않았을 때이 오류가 발생했습니다.


0

저에게는로드 밸런서 / URL 문제였습니다. 로드 밸런서 뒤의 웹 서비스는 다음과 같은 전체 URL을 사용하여 동일한로드 밸런서 뒤의 다른 서비스를 호출 loadbalancer.mycompany.com합니다. localhost.mycompany.com대신 사용하여 두 번째 서비스를 호출 할 때로드 밸런서를 우회하도록 변경했습니다 .

로드 밸런서에서 일종의 순환 참조 문제가 발생했다고 생각합니다.


-2

이 문제에 대한 해결책은 아니지만 Ektron eSync에서 위의 오류가 발생하는 경우 데이터베이스의 디스크 공간이 부족한 것일 수 있습니다.

편집 : 사실 이것은 Ektron eSync만의 문제가 아닙니다. 이는 전체 데이터베이스를 쿼리하는 모든 서비스에서 발생할 수 있습니다.

편집 : 디스크 공간이 부족하거나 필요한 디렉토리에 대한 액세스를 차단하면이 문제가 발생합니다.


이것은 질문에 대한 답을 제공하지 않습니다. 작성자에게 비평이나 설명을 요청하려면 게시물 아래에 댓글을 남겨주세요. 언제든지 자신의 게시물에 댓글을 달 수 있으며, 충분한 평판얻으면 모든 게시물댓글 수 있습니다 .
Dariusz

2
나는 그의 질문에 "어떻게 해결해야 할까?"라고 대답했는데, 그가 Ektron을 사용하고 있는지 여부에 대한 세부 사항을 우리에게주지 않은 것은 내 잘못이 아닙니다. 또한 그의 게시물에 댓글을 달려면 50 명의 담당자가 필요합니다.
Jonathan Bick 2013-08-15
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.