WCF 优化与高速服务






4.77/5 (19投票s)
通过客户端服务缓存和实例管理实现高速 WCF 服务
引言
我一直在考虑分享一些 WCF 服务优化技术,这些技术我们可以轻松地作为服务框架和服务客户端的一部分来实现。 本文讨论了以下重要几点
- 客户端服务缓存(服务池)
- 服务的动态绑定
- 对象缓存(对象池)
- 服务实例管理
-
在 XML 中轻松映射业务对象
本文没有什么新内容,除了使用 C# 列表对象来缓存来自服务的服务和对象。 这包括一个 XML 文件,该文件很容易将对象及其类型映射到使用工厂模式在运行时创建对象。
UML 高级设计图展示了本文中解释的所有内容。 我相信我们可以在这个项目中做更多优化,但目前我只想展示几个我们可以提高服务通信性能的领域。
WCF 服务调用中最耗时的过程是什么?
在任何服务调用或任何对外部应用程序边界的调用中,最耗时的过程之一是在通道上启动和打开连接。 这就是我们需要连接池的地方。 在 WCF 服务调用中,我们可以通过在客户端缓存服务通道轻松实现这一点。 本文为您提供了通道缓存和对象缓存,以提高速度。
下图将阐明一切

必备组件
您需要 VS 2010 才能打开解决方案,但我相信如果您创建另一个 VS 2008 解决方案并添加这些文件,则相同的代码也将在 VS 2008 中工作。
解决方案概览
如果您查看下图,您可以轻松理解包含的不同层和文件。 也许您可以下载附加代码并深入研究每个文件以获取有关实现的更多信息。

Using the Code
下面的代码执行客户端服务缓存。 它也经过了多线程测试,因为多个线程将异步访问缓存集合对象。
public static I CreateInstance<I>() where I : class
{
string endPointConfig = typeof(I).Name.ToString();
lock (_channels.SyncRoot)
{
if (_channels.ContainsKey(endPointConfig) == false)
{
_channels.Add(endPointConfig, OpenChannel<I>());
}
else if (((((IClientChannel)_channels[endPointConfig]).State ==
CommunicationState.Faulted)) ||
(((IClientChannel)_channels[endPointConfig]).State ==
CommunicationState.Closed) ||
(((IClientChannel)_channels[endPointConfig]).State ==
CommunicationState.Closing))
{
//If the channel is faulted. The existing channel will be removed from the cache
//and recreate the channel again.
((IClientChannel)_channels[endPointConfig]).Abort();
((IClientChannel)_channels[endPointConfig]).Close();
_channels.Remove(endPointConfig);
_channels.Add(endPointConfig, OpenChannel<I>());
}
return _channels[endPointConfig] as I;
}
}
这部分代码用于创建通道并打开通道。
private static I OpenChannel<I>() where I : class { string endPointConfig = typeof(I).Name.ToString(); ChannelFactory<I> factory = new ChannelFactory<I>(endPointConfig); factory.Open(); I channel = factory.CreateChannel(); ((IClientChannel)channel).Faulted += new EventHandler(ServiceFactory_Faulted); return channel; }
当服务出现故障时会执行这部分代码,同时我们需要从缓存集合中删除。
static void ServiceFactory_Faulted(object sender, EventArgs e)
{
((ICommunicationObject)sender).Abort();
((ICommunicationObject)sender).Close();
Type typ = ((ICommunicationObject)sender).GetType();
lock (_channels.SyncRoot)
{
((ICommunicationObject)sender).Faulted -= new EventHandler(ServiceFactory_Faulted);
_channels.Remove(typ.Name);
}
}
这部分代码执行对象池,并在服务调用业务对象时在服务主机中使用。
ObjectFactory.cs
public static I CreateInstance<I>() where I : class
{
lock (_pooledObjects.SyncRoot)
{
if (_pooledObjects.ContainsKey(typeof(I)) == false)
{
_pooledObjects.Add(typeof(I), GetInstance<I>());
}
return _pooledObjects[typeof(I)] as I;
}
// return GetInstance<I>() as I;
}
就这样 - 很简单
我希望这种方法非常简单并且易于实现。 请看一下,如果您喜欢这篇文章,请留下投票和评论。 谢谢。 欢迎任何评论和问题。
关注点
我一直专注于通过简单的自定义方法提供高性能应用程序。 我花了一些时间来调整 WCF 服务,借助许多内存分析器,例如蚂蚁分析器。