与单个请求相关的创建/关闭啥:ChannelFactory 或创建的 Channel?

Posted

技术标签:

【中文标题】与单个请求相关的创建/关闭啥:ChannelFactory 或创建的 Channel?【英文标题】:What to create/close in relation to individual request: ChannelFactory or created Channel?与单个请求相关的创建/关闭什么:ChannelFactory 或创建的 Channel? 【发布时间】:2012-03-07 22:34:43 【问题描述】:

我正在重构一个通过 wcf 进行进程间通信的大型程序。由于客户端可以直接访问服务接口,因此使用通道工厂来创建通道,因此不需要额外的客户端服务存根。通信包含许多高频请求的大消息(当前使用 NetTcpBinding,我正在考虑切换到 NetNamedPipeBinding)。

我的问题是关于创建/关闭频道与创建/关闭频道工厂之间的区别。更准确地说:channelfactory 创建了一个通道。现在,关于单个请求:我应该创建和关闭 channelfactory 以及与单个请求相关的通道(参见解决方案 2)还是仅创建/在性能方面更安全/更好?关闭与单个请求相关的通道,并使通道工厂为多个请求打开(参见解决方案 1)。

1)

//set up the channel factory right when I start the whole applicaton
ChannelFactory<IMyService> cf = new ChannelFactory<IMyService>();

//call this trillion of times over time period of hours whenever I want to make a request to the service; channel factory stays open for the whole time
try

    IMyService myService = cf.CreateChannel();
    var returnedStuff = myService.DoStuff();
    ((IClientChannel)myService).Close();

catch ...

//close the channel factory when I stop the whole application
cf.Close();

2)

//call this trillion of times over time period of hours whenever I want to make a request to the service
try

    ChannelFactory<IMyService> cf = new ChannelFactory<IMyService>();
    IMyService myService = cf.CreateChannel();
    var returnedStuff = myService.DoStuff();
    cf.Close();

catch ...

有什么实际区别?正确的方法是什么?还有更好的选择吗?

【问题讨论】:

您使用什么绑定来与服务通信? ChannelFactory&lt;T&gt; 实现 IDisposable,其清理应由 using 语句处理。 目前使用 nettcp 作为绑定。我正在考虑切换到命名管道,但考虑到当前架构,这将是一个重大变化。 我正在使用带有关闭/中止的 try-catch 模式。我已经阅读了推荐用于 wcf 而不是 using 语句的内容,因为对 close 的调用可能会导致异常。 ***上有几个关于这个的线程。但我的问题是关于关闭通道与通道工厂的区别。所以它是关于什么时候关闭,而不是关于如何关闭。我更正了我最初的问题,希望它变得更清楚。 【参考方案1】:

根据http://www.danrigsby.com/blog/index.php/2008/02/26/dont-wrap-wcf-service-hosts-or-clients-in-a-using-statement/

你应该这样做:

ChannelFactory<IMyService> channelFactory = null;
try

    channelFactory =
        new ChannelFactory<IMyService>();
    channelFactory.Open();

    // Do work...

    channelFactory.Close();

catch (CommunicationException)

    if (channelFactory != null)
    
        channelFactory.Abort();
    

catch (TimeoutException)

    if (channelFactory != null)
    
        channelFactory.Abort();
    

catch (Exception)

    if (channelFactory != null)
    
        channelFactory.Abort();
    
    throw;

这背后的主要原因是,如果您在 ChannelFactory 上调用 Dispose(),而后者又调用 Close(),如果底层 Channel 处于中止状态,则可能会引发异常。

【讨论】:

是的,这是关于 using-statement 与 try and catch。但我的问题是关于关闭通道与关闭通道工厂之间的区别。更准确地说:channelfactory 创建了一个通道。现在我有两件事可以关闭:通道和通道工厂。关于单个请求:我是否应该在每个单独请求之后关闭通道工厂以及通道,或者仅关闭通道并保持通道工厂打开在性能方面更好/更安全/更好。【参考方案2】:

不是对我最初的问题的直接回答,但我已经看到 ChannelFactory 上有一个静态的 CreateChannel 方法,可以用来创建通道。我现在使用这种方法来创建通道,因此,我不必再处理通道工厂实例了。因此,我使用静态工厂方法在每个请求之前创建客户端通道,然后关闭它(通道)。

【讨论】:

【参考方案3】:

创建通道工厂最多可能需要 70 毫秒(在我正在处理的应用程序中)。 创建通道(相比之下,从现有通道工厂创建通道相对较快)。如果您的客户端通常使用相同的凭据与主机通信,您应该考虑为每个使用的服务接口缓存一个通道工厂。如果您这样做,您将看到显着的性能改进。在您的问题中,这将与您描述的第二个选项更密切相关。

Darin Damitrov 在这里发表了一篇有趣的文章:-

creating WCF ChannelFactory<T>

【讨论】:

以上是关于与单个请求相关的创建/关闭啥:ChannelFactory 或创建的 Channel?的主要内容,如果未能解决你的问题,请参考以下文章

ChannelFactory:Channel Close() 未关闭连接(netstat 显示 ESTABLISHED)

REST API - 在单个请求中批量创建或更新 [关闭]

与android线程相关的looper、handler等术语是啥?这些类有啥关系? [关闭]

Struts中DispatchAction和Action类有啥不同?

性能指标公式平均每个用户发出的请求数量R=u*C*T/VU公式中u是啥意思

在 redux 中使用 thunk 中间件与使用常规函数作为异步操作创建者相比有啥好处? [关闭]