与单个请求相关的创建/关闭啥: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<T>
实现 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)
与android线程相关的looper、handler等术语是啥?这些类有啥关系? [关闭]
Struts中DispatchAction和Action类有啥不同?