2012-04-18 3 views
1

오랜 시간 ASP.Net 인터페이스 개발자가 WCF를 배우고 더 많은 아키텍처 관련 프론트에 대한 교육을 찾고 있습니다. 나는 거래해야한다.WCF 클라이언트 프록시, ASP.Net의 클라이언트/채널 캐싱 - 코드 검토

우리의 현재 ASMX 세계에서 우리는 웹 서비스와의 상호 작용을 위해 ServiceManager 정적 클래스를 만드는 모델을 채택했습니다. 우리는 WCF로 이전하기 위해 동일한 모델을 따르려고합니다. 처음에 나는 성능 문제를 다루고 있었지만, 조금 비틀었다. 그리고 지금은 원활하게 운영되고 있지만, 나는 전술에 의문을 제기하고있다.

public static class ContentManager 
{ 
    private static StoryManagerClient _clientProxy = null; 
    const string _contentServiceResourceCode = "StorySvc"; 

    // FOR CACHING 
    const int _getStoriesTTL = 300; 
    private static Dictionary<string, GetStoriesCacheItem> _getStoriesCache = new Dictionary<string, GetStoriesCacheItem>(); 
    private static ReaderWriterLockSlim _cacheLockStories = new ReaderWriterLockSlim(); 

    public static Story[] GetStories(string categoryGuid) 
    { 
     // OMITTED - if category is cached and not expired, return from cache 

     // get endpoint address from FinderClient (ResourceManagement SVC) 
     UrlResource ur = FinderClient.GetUrlResource(_contentServiceResourceCode); 

     // Get proxy 
     StoryManagerClient svc = GetStoryServiceClient(ur.Url); 

     // create request params 
     GetStoriesRequest request = new GetStoriesRequest{}; // SIMPLIFIED 
     Manifest manifest = new Manifest{}; // SIMPLIFIED 

     // execute GetStories at WCF service 
     try 
     { 
      GetStoriesResponse response = svc.GetStories(manifest, request); 
     } 
     catch (Exception) 
     { 
      if (svc.State == CommunicationState.Faulted) 
      { 
       svc.Abort(); 
      } 

      throw; 
     } 

     // OMITTED - do stuff with response, cache if needed 
     // return.... 
    } 

    internal static StoryManagerClient GetStoryServiceClient(string endpointAddress) 
    { 
     if (_clientProxy == null) 
      _clientProxy = new StoryManagerClient(GetServiceBinding(_contentServiceResourceCode), new EndpointAddress(endpointAddress)); 

     return _clientProxy; 
    } 

    public static Binding GetServiceBinding(string bindingSettingName) 
    { 
     // uses Finder service to load a binding object - our alternative to definition in web.config 
    } 

    public static void PreloadContentServiceClient() 
    { 
     // get finder location 
     UrlResource ur = FinderClient.GetUrlResource(_contentServiceResourceCode); 

     // preload proxy 
     GetStoryServiceClient(ur.Url); 
    }  
} 

우리는 왕복으로 지금 원활하게 실행하고있는 100ms의 범위 내에서 완료 호출 : 여기에 우리가 무슨 일을하는지의 단순화 된 버전 (제거 오류 처리, 캐싱, 객체 조작 등)입니다. PreloadContentServiceClient() 메소드를 생성하고 global.asax에 추가하면 "첫 번째 호출"성능이 같은 수준까지 내려갑니다. DataContractSerializer와 "서비스 참조 추가"메서드를 사용하고 있음을 알고 싶을 수도 있습니다.

정적 클래스, 싱글 톤, 공유 데이터 계약 어셈블리, ChannelFactory 패턴을 사용하는 방법, 그리고 우리의 사용 모델에 할 수있는 많은 것들을 많이 읽었습니다. 그것의 내 머리 위로 갔다. 그리고 제가 말한 것처럼, 우리는 매끄럽게 달리고있는 것처럼 보입니다. 나는 큰 그림을 보지 않고있는 것을 알고있다. 누군가 내가 채널 풀링, 프록시 실패 등과 관련하여 여기서 끝난 것을 말해 줄 수 있습니까? 왜 제가 ChannelFactory 경로로 향해야합니까? 내 직감은 그냥 해내겠다고 말하지만 내 머리는 왜 그걸 이해할 수없는 ...

고마워!

+1

예외 처리 코드는 WCF 프록시와 관련되어 있으므로 질문에 포함해야합니다. 예외 처리에 필요한 로직에 대한 간략한 개요는이 [blog post] (http://omaralzabir.com/do-not-use-using-in-wcf-client/)를 참조하십시오. 또한 구성에서 netTcpBinding을 사용하도록 변경된 WCF 서비스 및 클라이언트로 앱의로드 테스트를 만들어보십시오. WCF 프록시의 부적절한 폐기가 발생하면 netTcpBinding을 통해 지속적인 부하가 발생합니다. –

+1

방금 ​​위의 코드에서 서비스 작업과 관련된 try/catch 블록을 추가했습니다. 이 시점에서 멋진 것은 없습니다. 내가 링크 된 블로그 게시물에서 알아챈 한 가지는 작업 완료 후 client.Close()를 사용하는 것입니다. 클라이언트를 종료해야한다면 다음 호출을 빠르게 진행할 준비가 된 채널이있는 목적을 무효화 할 수 있습니까? – mcnejef

+0

Microsoft는 WCF 채널에 대해 IDisposable을 구현할 때 특정 디자인 결정을 내린 데 참조 된 것과 비슷한 사용 패턴이 필요하므로 네트워크 리소스가 적절히 릴리스됩니다. 분당 요청 수가 적은 클라이언트에서 WCF 서비스를 호출하는 경우 .NET GC가 결국 리소스를 복구 할 수 있도록 허용 할 수 있습니다. 이 블로그 게시물을 읽어 보시기 바랍니다. (http : //blogs.msdn.com/b/jjameson/archive/2010/03/18/avoiding-problems-with-using-statement-and-wcf-service-proxies.aspx)를 읽고이 기사의 링크를 따라 전체 내용보기 . –

답변

1

ChannelFactory는 일반적으로 당신이 서비스 참조 추가 사용하지 않을 때 사용됩니다 - 당신은 WSDL을 통해 생성되지 않은 공유 어셈블리를 통해 계약을 체결. 서비스 추가 참조은 본질적으로 무대 뒤에서 WCF 채널을 만드는 ClientBase을 사용합니다.

REST-ful 서비스를 다루는 경우 WebChannelFactory은 공유 어셈블리 계약을 기반으로하는 서비스 클라이언트와 같은 인터페이스를 제공합니다. 서비스가 REST-ful 엔드 포인트 바인딩 만 지원하는 경우 서비스 참조 추가을 사용할 수 없습니다.

유일한 차이점은 기본 설정입니다. 사용자 정의 동작, 바인딩 등을 위해 채널에 전체 액세스 권한이 필요합니까? 서비스 참조 추가 + SOAP은 사용자에게 필요한 인터페이스를 충분히 제공합니다.

+0

우리는 각각의 메소드 호출에 대해 Request와 Response 객체를 사용하는 모델을 좋아합니다. 요청 객체에 다른 필터를 추가하거나 응답에 추가 필드를 추가하는 것처럼 클라이언트의 모든 인스턴스를 한 번에 업그레이드 할 필요없이 서비스 역방향 호환을 쉽게 유지할 수 있습니다. 두 가지 방법을 모두 사용하여 유사한 결과물을 얻을 수 있다면 입력 된 공유 데이터 계약을 사용하지 않는 것이 좋습니다. REST는 필요 없지만 적어도 ... – mcnejef