WCF客户端代理,ASP.Net中的客户端/通道缓存 - 代码审查

时间:2012-04-18 20:29:00

标签: asp.net wcf proxy client channelfactory

长期以来,ASP.Net界面开发人员被要求学习WCF,在更多架构相关方面寻找一些教育 - 因为它不是我的强项,但我不得不处理。

在我们当前的ASMX世界中,我们采用了一种为Web服务交互创建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);
    }    
}

我们现在正在顺利运行,并且在100毫秒范围内完成往返呼叫。创建PreloadContentServiceClient()方法并添加到我们的global.asax使得“第一次调用”性能下降到同一级别。您可能想知道我们正在使用DataContractSerializer和“添加服务引用”方法。

我已经完成了很多关于静态类,单例,共享数据契约程序集,如何使用ChannelFactory模式以及我可以对我们的使用模型做的其他一些事情的阅读......不可否认,一些它超越了我的脑海。而且,就像我说的,我们似乎运行顺利。不过,我知道我看不到大局。有人可以告诉我这里有关于频道池,代理失败等问题的最终结果以及为什么我应该沿着ChannelFactory路径前进?我的直觉说要做到这一点,但我的脑袋无法理解为什么......

谢谢!

1 个答案:

答案 0 :(得分:1)

ChannelFactory通常在您不使用添加服务引用时使用 - 您通过不通过WSDL生成的共享程序集获得合同。 添加服务参考使用ClientBase,它实际上是在幕后为您创建WCF频道。

当您处理REST-ful服务时,WebChannelFactory基于共享程序集合同提供类似于服务客户端的接口。如果您的服务仅支持REST-ful端点绑定,则不能使用添加服务引用

与您的唯一区别是首选项 - 您是否需要完全访问自定义行为,绑定等渠道?添加服务参考 + SOAP为您提供足够的界面以满足您的需求。