如何提高WCF数据服务性能

时间:2010-10-12 16:38:54

标签: wcf wcf-ria-services wcf-data-services astoria

我是WCF数据服务的新手,所以我一直在玩。经过一些初步测试后,我对测试数据服务的性能感到失望。

我意识到因为WCF DS是基于HTTP的,协议中固有的开销,但我的测试仍然比我预期的慢:

环境:

  • 全部在一个盒子上:四核64位笔记本电脑,4GB内存,运行W7。体面的机器。
  • 小型SQL数据库(SQLExpress 2008 R2),包含16个表...正在测试的表有243行。
  • 使用所有默认值在IIS中托管我的测试服务。

代码:

  • 我为这个数据库创建了一个实体框架模型(DataContext)(VS2010的股票代码)。
  • 我已经基于这个模型创建了一个数据服务。
  • 我创建了一个客户端,该服务器具有此服务的直接服务引用(ObjectContext)(VS2010的股票代码)
  • 在客户端我也可以直接调用EF模型并使用Native SQL(ADO.NET SqlConnection)

测试计划:

  • 每次迭代都连接到数据库(有一个重用连接的选项),查询目标表中的所有行(“EVENTS”),然后对它们进行计数(从而强制执行任何延迟的提取)。
  • 为Native SQL(SqlConnection / SqlCommand),实体框架(DataContext)和WCF数据服务(ObjectContext)分别运行25次迭代。

结果:

  • Native SQL的25次迭代:436ms
  • 实体框架的25次迭代:656ms
  • WCF数据服务的25次迭代:12110ms

哎哟。这比EF慢了约20倍。

由于WCF数据服务是HTTP,因此没有机会进行HTTP连接重用,因此每次迭代都会强制客户端重新连接到Web服务器。但肯定会有比这更多的事情。

EF本身相当快,并且同样的EF代码/模型被重用于服务和直接到EF客户端测试。对数据服务中的Xml序列化和反序列化会有一些开销,但那么多!?!我过去在Xml序列化方面表现不错。

我将使用JSON和协议缓冲区编码运行一些测试,以确定我是否可以获得更好的性能,但我很好奇社区是否有任何关于加快这一点的建议。

我对IIS不太满意,所以也许有一些IIS调整(缓存,连接池等)可以设置来改善这个?

8 个答案:

答案 0 :(得分:2)

考虑部署为Windows服务吗? IIS可能具有ASAPI过滤器,重写规则等。即使这些都不是活动的,IIS管道也是如此之长,有些东西可能会让你慢慢减速。

服务应该为您提供一个良好的基线,说明在没有IIS减速的情况下运行,打包等请求需要多长时间

答案 1 :(得分:2)

以下链接的视频包含一些有趣的WCF基准以及WCF数据服务与实体框架之间的比较。

http://www.relationalis.com/articles/2011/4/10/wcf-data-services-overhead-performance.html

答案 2 :(得分:2)

通过启用压缩,我将WCF数据服务API的性能提高了41%。这很容易做到。请点击此链接,说明您的IIs服务器上的操作:Enabling dynamic compression (gzip, deflate) for WCF Data Feeds, OData and other custom services in IIS7

改变后不要忘记iisReset!

在客户端:

// This is your context basically, you should have this code throughout your app.
var context = new YourEntities("YourServiceURL");
context.SendingRequest2 += SendingRequest2;

// Add the following method somewhere in a static utility library
public static void SendingRequest2(object sender, SendingRequest2EventArgs e)
{
    var request = ((HttpWebRequestMessage)e.RequestMessage).HttpWebRequest;
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
}

答案 3 :(得分:1)

尝试在配置的绑定部分中将安全性设置为“none”。这应该会有很大的改进。

答案 4 :(得分:0)

为了消除大部分连接开销,您可以尝试将所有操作批量处理到WCF DS,以查看是否会产生显着差异。

NorthwindEntities context = new NorthwindEntities(svcUri);
var batchRequests = 
     new DataServiceRequest[]{someCustomerQuery, someProductsQuery};

var batchResponse = context.ExecuteBatch(batchRequests);

有关详细信息,请参阅here

答案 5 :(得分:0)

如何为WCF传递这25次迭代?

var WCFobj = new ...Service();
foreach(var calling in CallList)
   WCFobj.Call(...)

如果您这样打电话,则意味着您拨打WCF 25次,这会占用太多资源。

对我来说,我曾经将所有内容构建成DataTable和用户表名称,以便我正在调用的存储过程; DataRow是params。调用时,只需使用

以加密形式传递DataTable
var table = new DataTable("PROC_CALLING")...
...
StringBuilder sb = new StringBuilder();
var xml = System.Xml.XmlWriter.Create(sb);
table.WriteXml(xml);
var bytes = System.Text.Encoding.UTF8.GetBytes(sb.ToString());
[optional]use GZip to bytes
WCFobj.Call(bytes);

事情是你一次通过所有25个电话,这可以显着节省性能。如果返回对象是相同的结构,只需将其作为DataTable以字节形式传递,然后将其转换回DataTable

我曾经使用GZip为导入/导出数据模块实现此方法。传递大量字节会使WCF不满意。它取决于你想要消费的东西;计算资源或网络资源。

答案 6 :(得分:0)

WCF DataServices用于为您的不同客户端提供OpenData协议;因此您不必为每个更改请求编写/重构多个Web服务方法。如果整个系统都是基于微软技术的堆栈,我从不建议使用它。它适用于远程客户端。

答案 7 :(得分:-1)

要尝试的事情:

1)结果编码:如果可能,请使用WCF频道的二进制编码,请参阅http://msdn.microsoft.com/en-us/magazine/ee294456.aspx - 交替使用压缩:http://programmerpayback.com/2009/02/18/speed-up-your-app-by-compressing-wcf-service-responses/

2)更改服务实例行为,请参阅http://msdn.microsoft.com/en-us/magazine/cc163590.aspx#S6 - 尝试InstanceContextMode = InstanceContextMode.Single,ConcurrencyMode = ConcurrencyMode.Multiple - 如果您可以验证您的服务是以线程安全的方式构建的。

关于你的基准测试,我认为你应该模拟更真实的加载(包括并发用户)并忽略异常值,对IIS的第一个请求将非常慢(它必须加载所有的DLL)