【问题标题】:Push data to client, how to handle slow clients?推送数据到客户端,慢客户端如何处理?
【发布时间】:2015-05-26 16:55:17
【问题描述】:

在推送模型中,服务器将数据推送给客户端,如何处理带宽低或可变的客户端?

例如,我从生产者那里接收数据并将数据发送给我的客户(推送)。如果我的一个客户决定下载一个 linux iso,这个客户端的可用带宽变得太少而无法下载我的数据。

现在,当我的生产者生成数据并且服务器将其推送到客户端时,所有客户端都必须等到所有客户端都下载了数据。当有一个或多个带宽很小的慢速客户端时,这是一个问题。

我可以缓存要为每个客户端发送的数据,但由于数据量很大,这并不是一个真正的选择(大量客户端 * 数据大小 = 巨大的内存需求)。

这通常是如何解决的?不需要代码,只是一些想法/想法已经很受欢迎了。

【问题讨论】:

    标签: sockets network-programming client-server


    【解决方案1】:

    现在,当我的生产者生成数据并且服务器将其推送到 客户端,所有客户端都必须等到所有客户端都有 下载数据。

    上述情况不应该是这样 - 您的客户端应该能够彼此异步下载,每个客户端都保持自己独立的下载状态。也就是说,客户端 A 永远不必等待客户端 B 完成,反之亦然。

    我可以缓存要为每个客户端发送的数据,但是因为数据 大小很大,这不是一个真正的选择(很多客户 * 数据大小 = 巨大的内存需求)。

    正如沃伦在他的回答中所说,这个问题可以通过只保留一份数据副本而不是每个客户一份副本来减少。引用计数(例如,通过 shared_ptr,如果您使用 C++ 或其他语言的等效项)是确保共享数据仅在所有客户端完成下载后才被删除的简单方法。如有必要,您可以通过将数据分解成块来使共享更细粒度(例如,您可以将其分解为 800 个 1MB 块,而不是所有客户端都持有对单个 800MB linux iso 的引用,这样您就可以一旦所有客户端都下载了较早的块,就开始从内存中删除它们,而不必在每个客户端都下载完整个内容之前将整个 800MB 数据保存在内存中)

    当然,这种优化只能让你走到这一步——例如如果两个客户端分别请求不同的 800MB 文件,那么您最终可能需要 1.6GB 的 RAM 用于缓存,除非您想出更聪明的解决方案。

    您可以尝试以下一些可能的方法(从不太复杂到更复杂)。您可以单独或组合尝试其中任何一种:

    1. 监控每个客户端的“积压”有多少——也就是说,记录您缓存的等待发送到该客户端的数据量。还要跟踪服务器当前保存的缓存数据的字节数;如果该数字过高,则强制断开积压最大的客户端,以释放内存。 (当然,这不会为客户端带来良好的用户体验;但如果客户端有错误或连接速度较慢,那么无论如何他都不太可能获得良好的用户体验。它确实可以防止您的服务器崩溃或自行切换到死,因为单个客户端的连接不好)

    2. 跟踪您的服务器缓存了多少数据并等待发送出去。如果您缓存的数据量太大(对于某些适当的“太大”值),请暂时停止从将数据推送给您的套接字读取(或者如果您在内部生成数据,暂时停止生成它)。一旦缓存的数据量再次下降到可接受的水平,您就可以继续接收(或生成)更多要推送的数据。

    3. (这可能适用于您的用例,也可能不适用)修改您的数据模型,使其不再面向通信,而是面向状态。例如,如果您的目标是更新客户端的状态以匹配数据源的状态,并且您可以将数据源的状态组织成一组键/值对,那么您可以要求数据源在它发送的每条数据中都包含一个密钥。每当从数据源接收到键/值对时,只需将该键值对放入每个客户端的映射(或哈希表或其他一些面向键/值的数据结构)中(再次,这里使用 shared_ptr 或类似的保持合理的内存使用)。每当给定客户端耗尽其传出 TCP 数据队列时,从该客户端的键/值映射中删除最旧的项目,将其转换为 TCP 字节以发送,并将它们添加到传出 TCP 数据队列中。根据需要重复。这样做的好处是给定键的“过时”值会自动丢弃在服务器中,因此永远不需要发送给慢速客户端;相反,慢速客户端只会获得该给定键的“最新”值。这样做的好处是,给定客户端的最大“积压”将受到状态模型中键的数量的限制,而不管客户端的带宽有多慢或有多间歇。因此,速度较慢的客户端可能会看到较少的更新(每秒/分钟/小时),但考虑到其带宽,它看到的更新仍将是尽可能新的。

    【讨论】:

      【解决方案2】:

      只缓存一次数据,并让每个客户端处理程序跟踪它在下载中的位置,所有这些都使用相同的缓存。一旦所有客户端都拥有了所有数据,就可以删除缓存的数据了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-31
        • 2011-01-02
        • 2011-05-20
        • 2023-03-24
        • 2013-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多