【问题标题】:WCF Service Slow To Pass Objects. Is That Normal?WCF 服务传递对象缓慢。这正常吗?
【发布时间】:2012-02-23 14:36:34
【问题描述】:

我有一个用 C# 编写的 WPF 应用程序。它必须实例化数千个对象。从数据库服务器提取数据后,它必须运行大量需要时间的计算。整个过程需要 20-30 秒,其中 80% 来自计算。

因此,为了帮助解决此问题,我编写了一个 WCF 服务,该服务保留已实例化对象的副本以及已运行的计算,然后根据请求将实例化对象传输到调用客户端。

有效!然而它很慢......真的很慢。比原来的方式慢很多。从 WCF 服务传输所有对象需要 3-4 分钟,从而违背了它的目的。

我尝试过流式传输而不是缓冲服务,并在客户端和服务器配置文件中增加或减少不同的服务选项,但还没有找到真正有用的设置。

这是意料之中的缓慢速度,还是应该很快,我只需要修改一些选项?如果有,有哪些选择?

【问题讨论】:

  • 这可能归结为序列化。您使用什么协议端点?物体有多大?
  • 我使用 BasicHTTPBinding。对象使用 [Serializable] 属性进行序列化。所有对象的总大小约为 350 MB。
  • 我对 WCF 的建议是只通过网络传递所需的数据。正因为如此,我经常使用仅包含原始数据的 DTOPOCO 对象,以使进出 WCF 的数据尽可能小。 WCF 将比在本地运行项目要慢,因为它必须去服务器并获取其数据,而不仅仅是从内存中提取数据。您正在运行哪些类型的计算,而不能只将计算结果存储在对象本身上?
  • 如果这一切都发生在“内部”(即不是 Web 服务),则可能值得尝试使用套接字或命名管道,因为这会将您的对象序列化为二进制而不是 XML/文本。
  • 是的,@Rachel 也是这么说的。确保只序列化需要传输的值,如果可以的话,可能会创建轻量级对象。

标签: c# wpf wcf web-services


【解决方案1】:

WCF 不一定很慢,但如果应用程序设计不当,应用程序可能会很慢。这可以比作在跑车上装载几千磅的重量。这辆车一辆快车,但它并没有真正被正确使用。

首先,我想说您必须尽量减少通过网络发送的数据量(稍后会详细介绍)。一旦上线,如果您使用 TCP 或命名管道而不是 HTTP,您将获得更好的性能。见Choosing a Transport。 HTTP 很简单,因为大多数网络都配置为轻松通过,但它不是为大型数据集设计的。

如果延迟来自计算,那么 WCF 服务将完成的唯一一件事就是将处理从服务器卸载到客户端。最终,这可能是一件好事——甚至是必要的——如果您计划向服务器发送大量并发请求,但正如您所注意到的,这并不一定意味着最终用户的时间会更短。您应该重点做的是尽量减少计算时间。

很难给出具体细节,因为您没有透露太多关于正在查询的内容、正在返回的内容以及正在执行的计算。但是,通过Visual Studio SQL Server Projects 将代码从应用程序服务器卸载到数据库服务器,我在处理大型数据集时取得了令人印象深刻的结果。由于 .NET 和 MSSQL 都是在 CLR 上编写的,因此您可以用 C# 或 VB 或任何其他 CLR 语言编写本机数据库对象(如user defined functions)并将它们直接部署到数据库中。然后,您可以在查询中使用这些函数,并且它们非常快,因为它们被编译成原生 SQL。我已经看到在应用程序中运行 C# 与在数据库中运行相同函数之间存在数量级的差异。

【讨论】:

  • 谢谢!我正在考虑走CLR路线。我的方法的问题是计算已经运行。因此,即使服务器花了 20 分钟来运行计算,也没关系,因为它们已经完成并且服务已经缓存了对象。因此,当客户端说“给我对象”时,服务器不必重新实例化它们或重新运行计算,因为这已经完成了。相反,服务器只是说“当然,他们在这里”。不幸的是,这花了将近 5 分钟的时间。我可以尝试 TCP 或命名管道路由,但我需要它更快几个数量级。可不可能是?谢谢!
  • 抱歉,我不能确定 TCP/命名管道是否会快几个数量级。客户真的需要一次所有的信息,还是你可以逐步加载它? (通过分页或“无限滚动”或其他方式)
  • 我有不同的选择来处理它。这需要最少的重新架构,并且最适合当前的设计。但肯定还有其他选择。只是想确保通过更改设置不容易解决此速度问题。不过,我会检查 tcp/命名管道路由。感谢您的帮助
  • 我回应@Jeff 在这里所说的。我有一个 Web 应用程序,其中服务器连接到 WCF 服务,该服务从数据库返回 50k+ 条记录,进行一些计算并使用 linq 构建一些摘要。然而,提供的页面对列表进行了分页,一次加载到客户端的记录不超过 25 条。即使在负载下,响应时间也低于 1 秒。编辑:这有点误导,数据库返回 0-50k+,服务在 1 秒内返回 1K 条记录
  • 刚刚用 NetTCPBinding 实现了。绝对快得多,但仍然比在客户端实例化它并让客户端进行计算要慢。那好吧。感谢大家的帮助。
【解决方案2】:

如果您的应用程序 80% 的工作来自计算,那么将其中的某些部分并行化可能是个好主意,例如使用 Task Parallel Library

【讨论】:

  • 谢谢!是的,上周我尽可能地实施了 Plinq,这是速度上的重大改进。不过感谢您的提示!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多