发送 WCF 消息在负载下延迟

2024-05-01

当从自托管 WCF 服务向许多客户端(大约 10 个左右)发送消息时,有时消息的延迟时间比我预期的要长得多(发送到本地网络上的客户端需要几秒钟)。有谁知道为什么会这样以及如何解决它?


一些背景:该应用程序是股票行情式服务。它从第三方服务器接收消息并将它们重新发布到连接到该服务的客户端。尽可能快地发布消息非常重要,在大多数情况下,接收消息到将其发布到所有客户端之间的时间小于 50 毫秒(速度如此之快,以至于接近 DateTime.Now 的分辨率)。

在过去的几周里,我们一直在监控一些消息延迟 2 或 3 秒的情况。几天前,我们遇到了一个大高峰,消息延迟了 40-60 秒。据我所知,消息没有被丢弃(除非整个连接被丢弃)。这些延误似乎并非针对任何一位客户;它会影响所有客户端(包括本地网络上的客户端)。

我通过向线程池发送垃圾邮件来向客户端发送消息。消息到达后,我会为每个客户端的每条消息调用一次 BeginInvoke() 。其理论是,如果任何一个客户端接收消息的速度很慢(因为它正在拨号并下载更新或其他内容),则不会影响其他客户端。但这不是我所观察到的;看来所有客户端(包括本地网络上的客户端)都会受到类似持续时间的延迟影响。

我正在处理的消息量是每秒 100-400 条。消息包含字符串、guid、日期以及 10-30 个整数(具体取决于消息类型)。我观察到它们使用 Wireshark 时每个都小于 1kB。我们随时有 10-20 个客户端连接。

WCF 服务器托管在 Windows 2003 Web Edition Server 上的 Windows 服务中。我正在使用启用了 SSL/TLS 加密和自定义用户名/密码身份验证的 NetTCP 绑定。它具有 4Mbit 互联网连接、双核 CPU 和 1GB RAM,专用于此应用程序。该服务设置为 ConcurrencyMode.Multiple。服务进程即使在高负载下,CPU使用率也很少超过20%。

到目前为止,我已经调整了各种 WCF 配置选项,例如:

  • serviceBehaviors/serviceThrotdling/maxConcurrentSessions(当前为 102)
  • serviceBehaviors/serviceThrotdling/maxConcurrentCalls(当前为 64)
  • 绑定/netTcpBinding/绑定/maxConnections(当前为 100)
  • 绑定/netTcpBinding/绑定/listenBacklog(当前 100)
  • 绑定/netTcpBinding/binding/sendTimeout(当前为45秒,尽管我尝试过高达3分钟)

在我看来,一旦达到某个阈值,消息就会在 WCF 内排队(因此我一直在增加限制)。但要影响所有客户端,就需要最大化与一两个慢速客户端的所有传出连接。有谁知道 WCF 内部结构是否属实?

当我将传入消息发送给客户端时,我还可以通过合并传入消息来提高效率。然而,我怀疑存在一些潜在的问题,从长远来看,合并并不能解决问题。

WCF配置(公司名称已更改):

<system.serviceModel>
<host>
 <baseAddresses>
  <add baseAddress="net.tcp://localhost:8100/Publisher"/>
 </baseAddresses>
</host>

<endpoint address="ThePublisher"
                              binding="netTcpBinding"
                              bindingConfiguration="Tcp"
                                      contract="Company.Product.Server.Publisher.IPublisher" />
</behavior>

用于发送消息的代码:

    Private Sub HandleDataBackground(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs)
            If Me._FeedDataQueue.Count > 0 Then
                ' Dequeue any items received in last 50ms.
                While True
                    Dim dataAndReceivedTime As DataWithReceivedTimeArg
                    SyncLock Me._FeedDataQueue
                        If Me._FeedDataQueue.Count = 0 Then Exit While
                        dataAndReceivedTime = Me._FeedDataQueue.Dequeue()
                    End SyncLock

                    ' Publish data to all clients.
                    Me.SendDataToClients(dataAndReceivedTime)
                End While
            End If
    End Sub

    Private Sub SendDataToClients(ByVal data As DataWithReceivedTimeArg)
            Dim clientsToReceive As IEnumerable(Of ClientInformation)
            SyncLock Me._ClientInformation
                clientsToReceive = Me._ClientInformation.Values.Where(Function(c) Contract.CollectionContains(c.ContractSubscriptions, data.Data.Contract) AndAlso c.IsUsable).ToList()
            End SyncLock

            For Each clientInfo In clientsToReceive
                Dim futureChangeMethod As New InvokeClientCallbackDelegate(Of DataItem)(AddressOf Me.InvokeClientCallback)
                futureChangeMethod.BeginInvoke(clientInfo, data.Data, AddressOf Me.SendDataToClient)
            Next

    End Sub
    Private Sub SendDataToClient(ByVal callback As IFusionIndicatorClientCallback, ByVal data As DataItem)
        ' Send 
        callback.ReceiveData(data)
    End Sub

    Private Sub InvokeClientCallback(Of DataT)(ByVal client As ClientInformation, ByVal data As DataT, ByVal method As InvokeClientCallbackMethodDelegate(Of DataT))
        Try
            ' Send 
            If client.IsUsable Then
                method(client.CallbackObject, data)
                client.LastContact = DateTime.Now
            Else
                ' Make sure the callback channel has been removed.
                SyncLock Me._ClientInformation
                    Me._ClientInformation.Remove(client.SessionId)
                End SyncLock
            End If
        Catch ex As CommunicationException
            ....
        Catch ex As ObjectDisposedException
            ....
        Catch ex As TimeoutException
            ....
        Catch ex As Exception
            ....
        End Try
    End Sub

一种消息类型的示例:

 <DataContract(), KnownType(GetType(DateTimeOffset)), KnownType(GetType(DataItemDepth)), KnownType(GetType(DataItemDepthDetail)), KnownType(GetType(DataItemHistory))> _
 Public MustInherit Class DataItem
  Implements ICloneable

  Protected _Contract As String
  Protected _MessageId As Guid
  Protected _TradeDate As DateTime

  <DataMember()> _
  Public Property Contract() As String
   ...
  End Property

  <DataMember()> _
  Public Property MessageId() As Guid
   ...
  End Property

  <DataMember()> _
  Public Property TradeDate() As DateTime
   ...
  End Property

  Public MustOverride Function Clone() As Object Implements System.ICloneable.Clone
 End Class

 <DataContract()> _
 Public Class DataItemDepth
  Inherits DataItem

  Protected _VolumnPriceDetail As IList(Of DataItemDepthItem)

  <DataMember()> _
  Public Property VolumnPriceDetail() As IList(Of DataItemDepthItem)
   ...
  End Property

  Public Overrides Function Clone() As Object
   ...
  End Function
 End Class


 <DataContract()> _
 Public Class DataItemDepthItem
  Protected _Volume As Int32
  Protected _Price As Int32
  Protected _BidOrAsk As BidOrAsk ' BidOrAsk is an Int32 enum
  Protected _Level As Int32

  <DataMember()> _
  Public Property Volume() As Int32
   ...
  End Property

  <DataMember()> _
  Public Property Price() As Int32
   ...
  End Property

  <DataMember()> _
  Public Property BidOrAsk() As BidOrAsk  ' BidOrAsk is an Int32 enum
   ...
  End Property

  <DataMember()> _
  Public Property Level() As Int32
   ...
  End Property
 End Class

经过向 Microsoft 支持人员提出长期支持请求后,我们设法确定了该问题。

使用 Begin/End Invoke 委托模式调用 WCF 通道方法实际上会变成同步调用,而不是异步。

异步调用 WCF 方法的正确方法是除异步委托之外的任何方法,其中可能包括线程池、原始线程或 WCF 异步回调。

最后我用了WCF 异步回调 http://msdn.microsoft.com/en-us/library/ms731177.aspx(它可以应用于回调接口,尽管我找不到具体的例子)。

以下链接使这一点更加明确:https://learn.microsoft.com/en-us/archive/blogs/drnick/begininvoke-bugs https://learn.microsoft.com/en-us/archive/blogs/drnick/begininvoke-bugs

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

发送 WCF 消息在负载下延迟 的相关文章

  • 如何以编程方式找出哪台计算机是 Windows 中的域控制器?

    我正在寻找一种方法来确定客户端计算机连接到的给定域的域控制器的名称 IP 地址 在我们公司 我们有很多用于测试的小型网络 其中大多数都有自己的小域 作为示例 其中一个域被命名为 TESTLAB 我有一个 Windows XP 工作站 它是
  • PostgreSQL:在所有表字段的长度上创建索引

    我有一张桌子叫profile 我想按照填写最多的内容对它们进行排序 每列都是 JSONB 列或 TEXT 列 我不需要很大程度的确定性 所以通常我会按如下方式订购 SELECT FROM profile ORDER BY LENGTH CO
  • 增量SQL查询

    我的应用程序有一组固定的 SQL 查询 这些查询以轮询模式运行 每 10 秒一次 由于数据库的大小 gt 100 GB 和设计 超级规范化 我遇到了性能问题 每当数据库上发生更改查询结果的 CRUD 事件时 是否可以对给定查询进行增量更改
  • java charAt() 和startsWith() 哪个更快? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我的问题是 如果我想检查特定索引中字符串的一个字符 仅检查一个字符 哪种方法非常有效charAt or startsWith 我的意思是 据我所
  • Array.indexOf 如何比 Array.some 更高效

    这个问题的灵感来自于这个问题的竞争答案 具有多个参数的indexOf https stackoverflow com questions 39000151 indexof with multiple arguments 用户想知道一种有效的
  • 有效地生成所有排列

    我需要尽快生成所有排列 https en wikipedia org wiki Permutation整数的0 1 2 n 1并得到结果作为NumPy https numpy org 形状数组 factorial n n 或者迭代此类数组的
  • node-mongodb-native的插入性能

    我正在使用 MongoDB 测试 Node js 的性能 我知道其中每一个都很好 彼此独立 但我正在尝试一些测试来感受它们 我遇到了这个问题 但无法确定来源 问题 我正在尝试在单个 Node js 程序中插入 1 000 000 条记录 它
  • 为什么 Java 11 中对于空白字符串 String.strip() 比 String.trim() 快 5 倍

    我遇到过一个有趣的场景 因为某些原因strip 针对空白字符串 仅包含空格 明显快于trim 在Java 11中 基准 public class Test public static final String TEST STRING 3 w
  • 循环内的局部变量会被垃圾收集吗?

    我想知道将循环内引用的任何变量放在循环外是否更有效 或者它们可以像函数内的变量一样被垃圾收集吗 var obj key val for var i 0 i lt 10 i console log obj or for var i 0 i l
  • 优化数据可视化 Web 应用程序的性能

    我正在重写 3 年前编写的数据可视化网络工具 从那时起 浏览器的 JavaScript 引擎变得更快 所以我正在考虑将部分工作从服务器转移到客户端 在页面上 数据在表格和地图 或图表 中可视化 它使用相同的数据 但以不同的方式 因此准备显示
  • 在 C/C++ 中获得正模数的最快方法

    通常在我的内部循环中 我需要以 环绕 方式索引数组 因此 例如 如果数组大小为 100 并且我的代码要求元素 2 则应该给它元素 98 高级语言 例如 Python 可以简单地使用my array index array size 但由于某
  • Python——捕获异常的效率[重复]

    这个问题在这里已经有答案了 可能的重复 Python 常见问题解答 异常有多快 https stackoverflow com questions 8107695 python faq how fast are exceptions 我记得
  • iPhone 3GS 上的 ARM 与 Thumb 性能比较,非浮点代码

    我想知道是否有人有关于 iPhone 3GS 上 ARM 与 Thumb 代码性能的硬性数据 特别是对于非浮点 VFP 或 NEON 代码 我知道 Thumb 模式下的浮点性能问题 更大的 ARM 指令的额外代码大小是否会在某个时刻成为性能
  • 在单个 mongodb 查询中查找并计数

    我的文档看起来像这样 id ObjectId 572c4bffd073dd581edae045 name What s New in PHP 7 description PHP 7 is the first new major versio
  • Android 性能:SharedPreferences 的成本

    当我的应用程序启动时 我使用分片首选项中的值填充容器类 这个想法是处理 SharedPreferences 和 PreferenceManager 一次 因为我猜它们很重 这是一个示例 SharedPreferences prefs Pre
  • 即使在急切加载之后,belongs_to 关联也会单独加载

    我有以下关联 class Picture lt ActiveRecord Base belongs to user end class User lt ActiveRecord Base has many pictures end 在我的
  • 迭代列表的奇怪速度差异

    我创建了两个重复两个不同值的长列表 在第一个列表中 值交替出现 在第二个列表中 一个值出现在另一个值之前 a1 object object 10 6 a2 a1 2 a1 1 2 然后我迭代它们 不对它们执行任何操作 for in a1 p
  • Rails Windows Vagrant 响应时间非常慢

    我在跑 Vagrant 1 7 1 Rails 4 1 4 Thin 1 6 1 Windows 7 每个静态文件的发送时间都超过一秒 在我的 PC 上加载一个页面可能需要大约 20 秒 而在同事的 Linux 机器上则只需瞬间 有一些帖子
  • 如何用 kevent() 替换 select() 以获得更高的性能?

    来自Kqueue 维基百科页面 http en wikipedia org wiki Kqueue Kqueue 在内核和用户空间之间提供高效的输入和输出事件管道 因此 可以修改事件过滤器以及接收待处理事件 同时每次主事件循环迭代仅使用对
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不

随机推荐

  • 从集合类型 Oracle 12c 插入表 - ORA-00902: 无效数据类型

    我正在使用 Oracle 12 1 我以为我可以查询 12c 中的表类型 当我尝试执行此包时 我收到错误 ORA 00902 无效数据类型 我什至尝试使用强制转换多重集 但仍然出现同样的错误 我知道我们可以在数据库级别创建对象然后查询 但我
  • 工具提示出现在 intro.js 移动视图中的元素上方

    我正在使用 intro js 初步浏览我网站上的页面 该游览在桌面上看起来不错 但在移动设备上 工具提示出现在它所描述的元素的正上方 用户无法在移动视图中看到该元素 因为工具提示出现在该元素的正上方 见下图 我尝试自定义工具提示的位置 但输
  • CSS淡入淡出动画延迟计时

    我正在尝试使用 css3 创建幻灯片效果 我有三张图像 我需要将它们相互淡入淡出 每次转换需要持续 3 秒 第一张图像显示 3 秒 然后淡入第二张图像 第三张图像同样显示 我不确定如何计算关键帧的百分比 Codepen http codep
  • 每 x 秒对 SVG 元素进行动画处理

    介绍 我了解一些基本的动画技术SVG两者同时使用Javascript和 DOM
  • SymPy 无法对产品进行羔羊化

    我正在使用 SymPy 1 0 和 Python 2 7 我想计算前 100 个整数的总和 此代码运行成功 import sympy as sy from sympy tensor import IndexedBase Idx import
  • 为 bash 脚本创建应答文件

    我想为别人的 bash 脚本创建一个应答文件 当您运行 bash 脚本时 第一次安装该软件时 系统会询问您 5 个问题 我用的是yes script命令并且有效 它会自动应答yes对所有问题 不过我还是想回答一下no对于最后一个问题 有办法
  • 如何在 R 中创建 for 循环来进行这种特殊的计算

    我无法弄清楚这种 显然 简单的操作 给定这两个不同的数据框df A nrow 10 ncol 3 和df B n行 3 n列 3 df A df B col1 col2 col3 col1 col2 col3 1 2 4 1 4 5 3 5
  • JavaScript 中二维数组的 forEach() 和 Apply() 方法

    我有一个数组 其元素也是数组 每个数组包含三个元素 我想打电话给function calcMe a b c 对于我的主数组的每个元素使用forEach 方法 但我真的很困惑 不知道如何让它发挥作用 arr 1 5 4 8 5 4 3 4 5
  • Twitter API:如何知道使用哪个应用程序来关注

    在电子邮件通知中我们可以看到类似的内容
  • 如何在 Flex 中对 PHP 字符串使用换行符

    这是我的 MXML
  • 标记对话(或采访)的最语义方式?

    我试图找出最语义化的方式来标记这样的东西 John blah blah Paul blah blah George blah blah Ringo blah blah or John blah blah Paul blah blah Geo
  • 致命错误:CALL_AND_RETRY_LAST 分配失败 - JavaScript 堆内存不足错误

    我运行时收到此错误ng 构建 prod 92 块资产优化 4136 0155D210 443646 ms 标记 扫描 703 5 770 3 gt 703 6 759 8 MB 2162 2 0 0 ms 自标记开始以来 0 0 ms 0
  • JavaFX ProgressBar:如何添加动画?

    我创建了一个进度条并更改了进度条颜色 是否可以像 bootstrap 动画进度条一样向进度条添加动画 这是示例 链接在这里 http getbootstrap com components progress animated 实际上 我找到
  • 无法使用 Node npm 安装任何包

    我正在尝试通过 npm 安装一些节点包 但它不会安装 我已经尝试安装 卸载 更新节点 但似乎没有任何效果 我正在使用 ubuntu 12 04 以下是我尝试安装软件包的方式 npm install underscore npm http G
  • 使用 OpenCV 进行车牌识别

    我有一个项目 需要使用 OpenCV 识别汽车的车牌 我想加载数字或字母的图像 让 OpenCV 识别它并将其打印到控制台 有一个函数可以做到这一点吗 如果没有 我该怎么办 Note 我正在研究灰度级 请帮忙 我必须在一周后完成 谢谢你的快
  • ‘+= new EventHandler’和‘-= new EventHandler(anEvent)’之间的区别

    我看到一些代码使用 新的事件处理程序 anEvent 你能告诉我有什么不同吗 新的事件处理程序 Thanks 一个将委托添加到订阅者集合中 另一个将其删除 例如 如果您之前订阅了某个事件 但您希望在关闭表单时删除引用 则可以使用 版本 您将
  • 如何导出从 HTML DOM 解析器检索到的所有图像?

    我想要 使用从我的网站获取所有图像PHP 简单 HTML DOM 解析器 http simplehtmldom sourceforge net 并将它们全部导出到我的桌面ALL立刻 Not右键单击保存或屏幕截图 OPTIONAL 保存所有h
  • 如何在不实际调整大小的情况下触发 Control.Resize 事件?

    我不会对控件进行子类化 尝试通过触发事件Control Size Control Size失败 因为即使新大小实际上不同 它也不会触发 如果您要子类化Control 你可以打电话OnResize直接 或者将其暴露在 API 上 public
  • 如果您要使用的库尚不支持 Carthage 该怎么办

    我正在评估 Carthage 是否适合我的项目 我想找到答案的问题之一是当我想要使用的库 框架不支持 Carthage 时该怎么办然而 你们中有人曾经遇到过这个问题并找到了解决方案吗 Thanks 迦太基需要的主要东西是一个框架 并且该框架
  • 发送 WCF 消息在负载下延迟

    当从自托管 WCF 服务向许多客户端 大约 10 个左右 发送消息时 有时消息的延迟时间比我预期的要长得多 发送到本地网络上的客户端需要几秒钟 有谁知道为什么会这样以及如何解决它 一些背景 该应用程序是股票行情式服务 它从第三方服务器接收消