首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WCF通道和ChannelFactory缓存

WCF通道和ChannelFactory缓存
EN

Stack Overflow用户
提问于 2011-10-20 20:19:26
回答 3查看 17.2K关注 0票数 22

因此,我决定在我的WCF应用程序中稍微提高一些性能,并尝试缓存通道和ChannelFactory。在我开始之前,我有两个问题需要澄清。

( 1)应否将ChannelFactory作为单例实现?

2)对于如何缓存/重用单个通道,我有点不确定。你有如何做到这一点的例子你可以分享吗?

可能需要注意的是,我的WCF服务是作为一个独立的应用程序部署的,只有一个端点。

编辑:

谢谢你的回复。不过我还有几个问题..。

1)我想我对缓存应该在哪里发生感到困惑。我正在向我们公司的另一个部门提供使用此代码的客户端API。这种缓存是否发生在客户机上?

2)客户端API将被用作Silverlight应用程序的一部分,这会改变什么吗?特别是,在这种情况下可以使用哪些缓存机制?

3)我还不清楚GetChannelFactory方法的设计。如果我只有一个服务,应该只创建一个ChannelFactory并进行缓存吗?

我仍然没有实现任何缓存特性(因为我对它应该如何实现完全感到困惑!),但到目前为止,我对客户机代理的功能如下所示:

代码语言:javascript
复制
namespace MyCompany.MyProject.Proxies
{
    static readonly ChannelFactory<IMyService> channelFactory =
        new ChannelFactory<IMyService>("IMyService");

    public Response DoSomething(Request request)
    {
        var channel = channelFactory.CreateChannel();

        try
        {
            Response response = channel.DoSomethingWithService(request);
            ((ICommunicationObject)channel).Close();
            return response;
        }
        catch(Exception exception)
        {
            ((ICommenicationObject)channel).Abort();
        }
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-10-20 20:36:18

使用ChannelFactory创建工厂的实例,然后缓存该实例。然后,您可以根据需要/需要从缓存的站点创建通信通道。

您是否需要多个通道工厂(即.有多个服务)?在我的经验中,你会看到性能上最大的好处。创建一个通道是一项相当便宜的任务;它在一开始就设置了所有需要时间的东西。

我不会缓存单独的通道--我会创建它们,将它们用于操作,然后关闭它们。如果您缓存它们,它们可能会超时,通道将出现故障,那么您将不得不中止它并创建一个新的通道。

不确定为什么要使用单例来实现ChannelFactory,特别是如果要创建它并缓存它,而且只有一个端点。

稍后,当我有更多时间时,我将发布一些示例代码。

更新:代码示例

下面是一个示例,说明我是如何为工作中的项目实现这个功能的。我使用了ChannelFactory<T>,因为我正在开发的应用程序是一个n层应用程序,有几个服务,还会添加更多服务。目标是有一种简单的方法,在应用程序的每个生命周期中创建一次客户端,然后根据需要创建通信通道。这个想法的基本原理不是我的(我从网上的一篇文章中得到的),尽管我修改了实现以满足我的需要。

我在我的应用程序中有一个静态帮助类,在这个类中,我有一个字典和一种方法,可以从信道工厂创建通信通道。

字典如下(object是值,因为它将包含不同的通道工厂,每个服务一个)。我在示例中将"Cache“作为占位符--使用任何缓存机制替换语法。

代码语言:javascript
复制
public static Dictionary<string, object> OpenChannels
{
    get
    {
        if (Cache["OpenChannels"] == null)
        {
            Cache["OpenChannels"] = new Dictionary<string, object>();
        }

        return (Dictionary<string, object>)Cache["OpenChannels"];
    }
    set
    {
        Cache["OpenChannels"] = value;
    }
}

接下来是从工厂实例创建通信通道的方法。该方法首先检查工厂是否存在--如果不存在,则创建工厂,将其放入字典,然后生成通道。否则,它只会从工厂的缓存实例中生成一个通道。

代码语言:javascript
复制
public static T GetFactoryChannel<T>(string address)
{

    string key = typeof(T.Name);

    if (!OpenChannels.ContainsKey(key))
    {
        ChannelFactory<T> factory = new ChannelFactory<T>();
        factory.Endpoint.Address = new EndpointAddress(new System.Uri(address));
        factory.Endpoint.Binding = new BasicHttpBinding();
        OpenChannels.Add(key, factory);
    }

    T channel = ((ChannelFactory<T>)OpenChannels[key]).CreateChannel();

    ((IClientChannel)channel).Open();

    return channel;
}

我已经把这个例子从我在工作中使用的东西中删掉了一些。在这种方法中,您可以做很多事情--您可以处理多个绑定,为身份验证分配凭据等等。这几乎是您生成客户端的一站式购物中心。

最后,当我在应用程序中使用它时,我通常创建一个通道,做我的业务,并关闭它(如果需要的话,可以中止它)。例如:

代码语言:javascript
复制
IMyServiceContract client;

try
{
    client = Helper.GetFactoryChannel<IMyServiceContract>("http://myserviceaddress");

    client.DoSomething();

    // This is another helper method that will safely close the channel, 
    // handling any exceptions that may occurr trying to close.
    // Shouldn't be any, but it doesn't hurt.
    Helper.CloseChannel(client);
}
catch (Exception ex)
{
    // Something went wrong; need to abort the channel
    // I also do logging of some sort here
    Helper.AbortChannel(client);
}

希望上面的例子能给你提供一些可以继续下去的东西。我已经在生产环境中使用了类似的东西大约一年了,而且效果很好。我们遇到的任何问题中,99%通常与应用程序之外的东西有关(无论是外部客户端还是不受我们直接控制的数据源)。

如果有什么不清楚的地方让我知道,或者你还有更多的问题。

票数 23
EN

Stack Overflow用户

发布于 2011-10-21 06:18:49

你总是可以让你的ChannelFactory对每个WCF合同是静态的.

您应该知道,从.Net 3.5中,由于性能原因,通道工厂会将代理对象池化。调用ICommunicationObject.Close()方法实际上是将对象返回给池,希望它能够被重用。

如果您想要进行一些优化,那么我会查看分析器,如果您可以防止代码中只进行一个IO调用,那么它可能远远超过您将对通道工厂所做的任何优化。不要选择要优化的区域,使用分析器来找到可以优化的目标。例如,如果您有一个SQL数据库,您可能会在查询中找到一些低挂的结果,如果还没有对这些查询进行优化,这些结果将使性能提高数量级。

票数 5
EN

Stack Overflow用户

发布于 2012-04-02 14:40:58

创造频道需要付出很大的代价。实际上,如果您在客户机中使用ChannelFactory而不是纯ChannelFactory,WCF已经有了用于ChannelFactory的缓存机制。但缓存将过期,如果你做一些传统的操作(请谷歌它的细节,如果你想)。对于ErOx的问题,我找到了另一个解决方案,我认为这更好。见下文:

代码语言:javascript
复制
namespace ChannelFactoryCacheDemo
{
    public static class ChannelFactoryInitiator
    {
        private static Hashtable channelFactories = new Hashtable();

        public static ChannelFactory Initiate(string endpointName)
        {
            ChannelFactory channelFactory = null;

            if (channelFactories.ContainsKey(endpointName))//already cached, get from the table
            {
                channelFactory = channelFactories[endpointName] as ChannelFactory;
            }
            else // not cached, create and cache then
            {
                channelFactory = new ChannelFactory(endpointName);
                lock (channelFactories.SyncRoot)
                {
                    channelFactories[endpointName] = channelFactory;
                }
            }
            return channelFactory;
        }
    }
    class AppWhereUseTheChannel
    {
        static void Main(string[] args)
        {
            ChannelFactory channelFactory = ChannelFactoryInitiator.Initiate("MyEndpoint");
        }
    }

    interface IMyContract { }
}

如果您有另一个需求,您可以自己定制Initiate方法的逻辑和参数。但是,这个启动器类并不仅限于一个端点。它对于应用程序中的所有端点都是强大的。但愿能去。对你来说很好。顺便说一下。这个解决方案不是我给的。我从一本书上得到的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7841748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档