【问题标题】:How to limit / throttle bandwidth with *multiple* connections如何使用*多个*连接限制/节流带宽
【发布时间】:2010-10-27 03:25:24
【问题描述】:

我正在用 C# 编写一个应用程序,它使用到多个服务器的多个连接同时下载(在不同线程中), 并且我希望能够限制使用的带宽。

对于单个连接,解决方案很简单;我会使用这里发布的解决方案:http://www.codeproject.com/KB/IP/Bandwidth_throttling.aspx 它计算单个连接的休眠时间。

我想知道对多个连接执行此操作的最佳方法是什么。

使用上面发布的 ThrottledStream 并在连接之间平均分配带宽(比如 2MB/秒)是不正确的,如果我有 3 个非常慢的连接和 1 个非常快的连接,它们都将被限制为 512kb/秒,所以快速的一个不会超过 512kb/秒,而其他 3 个甚至都达不到。

我认为首选的解决方案是只限制最快的连接,以便最佳地使用较慢的连接。

有没有人对此有任何经验、示例代码或任何建议?

【问题讨论】:

    标签: c# limit bandwidth connection


    【解决方案1】:

    如果是我,我会先将带宽要求分成 N 个部分,其中 N 是并发连接数。接下来,我将监控每个连接的性能并根据需要进行调整。首先,我会确定以我设置的最大速度运行的任何连接。如果需要,这些连接将成为提高速度的候选者。接下来,我将确定那些不符合我提出的带宽限制的连接(成绩不佳者)。这样就很容易总结后一组的不足之处。您可以将这个数字除以以最高速度执行的连接数并进行调整。

    允许的总带宽:100KB/秒 连接数:5 初始每个连接限制:20KB/秒 实际结果: 连接 1:10KB/秒 连接 2:5KB/秒 连接 3:20KB/秒 连接 3:20KB/秒 连接 3:20KB/秒 总短:15KB/秒 新的每连接限制: 连接 1:10KB/秒 连接 2:5KB/秒 连接 3:25KB/秒 连接 3:25KB/秒 连接 3:25KB/秒

    然后您会每隔一段时间对其进行监控。

    【讨论】:

      【解决方案2】:

      在我的脑海中,我会得到一个收集器对象/类,它从每个流中按顺序提取,收集器在适当的时候处于休眠状态(可能通过移动平均比较)。这将平衡您的流,以便在一个比另一个慢时实现完整的带宽限制......您将轮询拉取,发现它是空的,然后在睡觉前拉下一个流。

      由于您的收集器受到提取的聚合数据/时间的限制,您将获得正确的客户端带宽。

      【讨论】:

        【解决方案3】:

        上面的总短实际上是 25kb/秒,但我不会将连接分成组,而是按速度排序并循环遍历它们。从总带宽开始,将新带宽设置为(剩余带宽/剩余计数)。这将保持 5k 和 10k 连接的限制,以防它们加速。您可以超出分配的带宽,但您会更正它。

        List<Connection> connections = GetConnections();
        connections.Sort(); // sorts by Speed
        bandwidth = 100000;
        for (int i = 0; i < connections.Count; i++)
        {
            Connection cnn = connections[i];
            cnn.SpeedLimit = bandwidth / (connections.Count - i);
            bandwidth -= Math.Min(cnn.Speed, cnn.SpeedLimit);
        }
        
        (start with all connections SpeedLimit set to 20000 bytes/sec)
        
        Speed   bandwidth SpeedLimit
        5000    100000  20000
        10000   95000   23750
        20000   85000   28333
        20000   65000   32500
        20000   45000   45000
        

        连接的总速度限制为 149583,因此如果慢速连接速度加快,您可以超过限制,但如果您每秒调整限制,它应该非常接近。

        连接速度更改为:5000、10000、28333、21000、45000,所以我们实际下载了 109,333 字节,但我们会再次调整。除 45k 之外的所有连接都已达到其可能的限制:

        Speed   bandwidth SpeedLimit
        5000    100000  20000
        10000   95000   23750
        21000   85000   28333
        28333   64000   32000
        45000   35667   35667 
        

        新的速度将是 5000、10000、21000、28333、35667、100k 准确

        Speed   bandwidth SpeedLimit
        5000    100000  20000
        10000   95000   23750
        21000   85000   28333
        28333   64000   32000
        35667   35667   35667
        

        现在让我们假设 5k 的连接速度高达 20k:

        Speed   bandwidth SpeedLimit
        10000   100000  20000
        20000   90000   22500
        21000   70000   23333
        28333   49000   24500
        35667   20667   20667
        

        【讨论】:

          【解决方案4】:

          我也有同样的问题。我正在尝试 VS2010 Pro,并且我制作了小型家庭项目,我正在同时下载多个文件(10-50)并且我想限制所有文件的带宽。我找到了这个帖子,但我真的看不到解决方案,所以我自己尝试了。

          我所做的是,我创建了一个非常简单的 DownloadLimiter 类。每次下载器想要下载一个块时(例如,就在 InputStream.Read() 之前),它必须向 DownloadLimiter 询问带宽。它有一个具有限制的变量,例如 50 000(如 bytesPerSecond)和 availableBandwidthPerSecond,随着每个 ask() 的处理和返回而减少。

          它还包含一个计时器,它每 1000 毫秒将 availableBandwidthPerSecond 重置为限制。

          ask() 方法被锁定,因此如果当前没有任何可用带宽,它只会循环并休眠一段时间,直到计时器重置可用带宽。

          不过,它运行良好。有一个问题。假设您的连接速度非常快(100 兆位),并且您将限制设置为 200kb。如果您下载一个文件(从类似的快速连接),那么您将在 x 毫秒内达到 100 兆位的峰值,然后它将等到可用带宽被重置。这将一直持续到文件完成。平均下载速度将相当均匀,但如果您查看带宽图,它每秒都会出现峰值。 我猜到 ThrottledStream 的发布链接与峰值的工作方式相同。

          我不知道上面的文字是否对您有所帮助...如果有人感兴趣,我可以将代码发布在某个地方供您阅读。一些优化(如果你愿意的话)也会很好,因为我还不太熟悉线程。 :)

          【讨论】:

          • 嗨,DavidMB,您介意发布 DownloadLimiter 类 吗?感谢西雅图的杰夫
          【解决方案5】:

          稍作调整,您就可以使用您在第一篇文章中链接的类,将 Throttle 和 Reset 放在静态类中。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-09-19
            • 1970-01-01
            • 2021-12-12
            • 2010-09-28
            • 1970-01-01
            • 2020-12-08
            相关资源
            最近更新 更多