오랜 시간 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 경로로 향해야합니까? 내 직감은 그냥 해내겠다고 말하지만 내 머리는 왜 그걸 이해할 수없는 ...
고마워!
예외 처리 코드는 WCF 프록시와 관련되어 있으므로 질문에 포함해야합니다. 예외 처리에 필요한 로직에 대한 간략한 개요는이 [blog post] (http://omaralzabir.com/do-not-use-using-in-wcf-client/)를 참조하십시오. 또한 구성에서 netTcpBinding을 사용하도록 변경된 WCF 서비스 및 클라이언트로 앱의로드 테스트를 만들어보십시오. WCF 프록시의 부적절한 폐기가 발생하면 netTcpBinding을 통해 지속적인 부하가 발생합니다. –
방금 위의 코드에서 서비스 작업과 관련된 try/catch 블록을 추가했습니다. 이 시점에서 멋진 것은 없습니다. 내가 링크 된 블로그 게시물에서 알아챈 한 가지는 작업 완료 후 client.Close()를 사용하는 것입니다. 클라이언트를 종료해야한다면 다음 호출을 빠르게 진행할 준비가 된 채널이있는 목적을 무효화 할 수 있습니까? – mcnejef
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)를 읽고이 기사의 링크를 따라 전체 내용보기 . –