2012-04-11 3 views
0

wcf 서비스에 수백 개의 동시 요청을 보낼 수있는 응용 프로그램이 있습니다. 서비스가 http 연합 바인딩을 노출하고 있습니다.WCF 클라이언트 성능 문제

현재 하나의 클라이언트와 TPL을 사용하여 여러 스레드에서 요청을 보내고 있습니다. windows가 최대 동시 요청 수 (2 개)를 wcf로 제한하지 않도록 system.net 최대 연결 설정을 1000으로 변경했습니다.

인증 토큰 등을 받기 때문에 초기 요청에 더 많은 시간이 소요됨을 알 수 있습니다. 그런 다음 요청 시간이 일반적으로 크게 줄어들지 만 서버 로그와 상관 관계가없는 일부 스파이크가 간헐적으로 발생합니다. 나는 가지고있다.

이것이 높은 스루 업 확장 성 높은 클라이언트에 접근하는 가장 좋은 방법인지 궁금합니다.

여러 스레드간에 공유 클라이언트 프록시를 사용하고 여러 스레드간에 ChannelFactory를 공유하려고했습니다. 모든 스레드는 TPL을 사용하여 완료됩니다.

양쪽 WCF 서비스와

<basicHttpBinding> 
     <binding name="Binding1" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:05:00" closeTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"> 
      <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/> 
      <security mode="TransportWithMessageCredential"> 
      <transport clientCredentialType="None" proxyCredentialType="None" realm=""/> 
      <message clientCredentialType="UserName" algorithmSuite="Default"/> 
      </security> 
     </binding> 
     </basicHttpBinding> 
+1

테스트 클라이언트 컴퓨터에는 몇 개의 CPU가 있습니까?일반적으로 진정한로드 테스트를 수행하려면 모든 스레드 및 요청을 생성하려고하는 클라이언트 시스템에서 처리 제한 사항을 실행할 때 여러 기계를 실행해야합니다. –

+0

나는 쿼드 코어 8 기가 바이트 상자 클라이언트 컴퓨터로, 그리고 정말 상자를 강조하지, 나는 각각 100 요청을 보내는 10 스레드를 실행하지만 samll 기간 서버에 대한 스파이크가 되길 바란다,하지만 그것은 doesnt –

+1

원한다면, 당신은 스레드 풀의 최소 스레드 수를 늘림으로써 "예열"기간을 줄일 수 있습니다. .net은 즉시 분당 최대 증가하고 초당 2 스레드와 같은 최대 값까지 미터 아웃합니다. –

답변

1

일부 생산 성능 문제가 표시됩니다 바인딩과 WCF 클라이언트에게 (직접 ClientBase 또는 ChannelFactory에)를 사용하여 많은 일을하도록 강요되는 .NET 가비지 수집기에 기인 지저분한 물건 처분 때문입니다. 성능 모니터를 사용하여 런타임시 .NET 가비지 수집기의 동작을 확인하여 스파이크를 유발하는지 확인합니다.

GC 문제인 경우 서비스 및 클라이언트 코드를 검토해야합니다. 서비스에서 오브젝트 인스턴스 범위가 가능한 한 제한되도록하십시오. 이렇게하면 인스턴스가 Gen0에서 가비지 수집이 가장 자주 발생하는 것을 보장 할 수 있습니다. 클라이언트 코드도 검토해야하지만 서비스 코드에서 특히 중요합니다. 또한

, 서비스하지만, 특히 클라이언트 모두에서는 IDisposable을 구현해야합니다 개체 인스턴스가 제대로 WCF 클라이언트 인스턴스를 제외하고 using에 싸여되어 있는지 확인하십시오. WCF 클라이언트의 적절한 처리를 처리하려면이 패턴을 확인하려면 brief blog post을보십시오. 종속성 주입 컨테이너를 사용하는 경우 까다로울 수 있습니다. 이유에 대한 자세한 내용은 "WCF 사용 안 함"을 검색 할 수 있습니다. BasicHttpBinding과 WsHttpBinding의 일부 구성은 엉성한 처분을 처리 할 수 ​​있지만 세션을 사용하는 모든 바인딩은 GC 문제가 발생하기 쉽습니다.

2

단일 클라이언트 인스턴스를 사용 중이며 TPL을 사용하여 작업을 팬 아웃하고 있다고 언급했습니다. WCF 클라이언트 인스턴스는 기술적으로 스레드로부터 안전하지 않습니다. 클라이언트를 만드는 데 드는 비용은 매우 싸기 때문에 작업이 끝나면 Close() 이상의 새로운 인스턴스를 만드는 것을 두려워해서는 안됩니다.

다음으로 TPL만으로는 동시성을 확보 할 수 없습니다. WCF 호출을 할 때는 네트워크 I/O와 서버의 응답을 기다리는 것이 전부입니다. 고객이 클라이언트에서 무엇을하고 있는지 확인하기 위해 필요한 것은 async WCF contracts입니다. 그런 다음 TPL의 Task.Factory.FromAsync과 결합하여 호출이 반환 된 후에 수행해야하는 다른 워크 플로를 함께 연결할 수 있습니다. 예 :

[ServiceContract] 
public interface IMyService 
{ 
    [OperationContract(AsyncPattern=true)] 
    IAsyncResult BeginDoSomething(); 
    SomeResultType EndDoSomething(IAsyncResult result); 
} 

// Somewhere in the client app you store your channel factory (these are "expensive", these you cache) 
ChannelFactory<IMyService> channelFactory = new ChannelFactory<IMyService>(); 

public void MyClientMethod() 
{ 
    // Create a client channel 
    IMyService myServiceChannel = channelFactory.CreateChannel(); 

    // Use TPL's FromAsync to invoke the async WCF call and wrap that up with the familiar Task API 
    Task<SomeResultType>.Factory.FromAsync(myServiceChannel.BeginDoSomething 
              myServiceChannel.EndDoSomething, 
              null) 
           .ContinueWith(antecdent => 
           { 
            try 
            { 
             // NOTE: exception will be thrown here if operation failed 
             SomeResultType result = antecedent.Result; 

             // ... continue processing the result ... 
            } 
            finally 
            { 
             // NOTE: depending on your configuration you might want to watch for errors and .Abort() here too 
             ((IClientChannel)myServiceChannel).Close(); 
            } 
           });  
} 

해당 클라이언트 호출에서 비동기 I/O를 사용하면 모든 확장 성이 생길 것입니다.

+0

내 테스트에서 일시적인 클라이언트는 항상 성능이 저하되고 가장 많은 CPU가 필요합니다. 이유는 ADFS에서 토큰을 가져와야 할 수도 있기 때문입니다. 또한 스레드간에 클라이언트를 공유 할 때, 스레딩은 결코 문제가되지 않았지만 TPL 및 비동기에 대한 좋은 포인터 –

+0

당신은 그저 운이 좋았을 것입니다. 구울 수있는 클라이언트 인스턴스에는 많은 공유 상태가 있습니다. 모든 종류의 동시성 문제와 마찬가지로 타이밍 때문에 항상 발생하는 것은 아닙니다. 인증에 관한 한,이를 완화 할 수있는 방법이 있어야합니다. 바인딩 구성에 관한 정확한 세부 정보로 질문을 업데이트 할 수 있습니까? 또한 단일 ChannelFactory 인스턴스를 사용하고 있습니까? –

+0

그럴 수도 있습니다. 채널 팩토리를 새로 만들 때마다 응답 시간이 좋지 않다고 생각합니까? –