Ajax 轮询与 SSE(服务器端的性能)

Posted

技术标签:

【中文标题】Ajax 轮询与 SSE(服务器端的性能)【英文标题】:Ajax polling vs SSE (performance on server side) 【发布时间】:2019-04-29 20:04:06 【问题描述】:

我很好奇,从服务器端的角度来看,对于何时使用 Ajax 轮询而不是 SSE 更好,是否存在某种标准限制。

每秒 1 个请求:我很确定 SSE 更好 每分钟 1 个请求:我很确定 Ajax 更好

但是每 5 秒 1 个请求呢?我们如何计算 Ajax 或 SSE 的极限频率在哪里?

【问题讨论】:

连接中缺少一些重要的细节,例如从服务器到客户端实际发送新数据的频率?很多空的民意调查真的是低效的。客户需要多快才能看到这些数据?这决定了推送与投票的适当性。 是的,但我更关心服务器端,而不是用户体验。假设我们每 10 秒需要新数据,在服务器上保持连接打开 10 秒什么都不做是不是浪费资源? 不,将空闲连接保持打开 10 秒并不浪费任何东西。事实上,它为您每 10 秒建立一个新连接节省了大量开销。想想这个。如果您的朋友打算在电话上每 10 秒对您说一声“哔”,他们会先打个电话,保持在线,然后每 10 秒对您说“哔”,还是会打电话给您,说哔,挂断,10 秒后再给你打电话,说哔哔声,挂断电话,等等……跟着我重复。空闲连接不会花费您任何费用,但一遍又一遍地建立新连接会。 【参考方案1】:

对于 Ajax 来说,每分钟 1 个请求不可能总是更好,所以这个假设从一开始就是有缺陷的。任何一种频繁的轮询几乎总是一个代价高昂的选择。从另一个问题的our previous conversation in comments 看来,您从一个信念开始,即开放的 TCP 套接字(无论是 SSE 连接还是 webSocket 连接)在某种程度上对服务器性能来说都是昂贵的。一个空闲的 TCP 连接占用零 CPU(可能每隔一段时间,可能会发送一次保持活动,但除此之外,空闲套接字不使用 CPU)。它确实使用了一些服务器内存来处理套接字描述符,但是经过高度调整的服务器一次可以有 1,000,000 个打开的套接字。因此,您的 CPU 使用率将更多地取决于正在建立的连接数以及每次建立连接时它们要求服务器做什么,而不是与有多少打开(并且大部分是空闲)连接有关。

请记住,每个 http 连接都必须创建一个 TCP 套接字(这是客户端/服务器之间的往返),然后发送 http 请求,然后获取 http 响应,然后关闭套接字。这是每分钟要做的大量数据往返。如果连接是 https,则由于加密层和端点认证,建立连接的工作量和往返次数就更多了。因此,如果您可以创建一个 SSE 连接,而客户端只是侦听通过该连接从服务器流式传输的数据,那么每分钟为数十万客户端执行所有这些操作似乎是对资源和带宽的巨大浪费。

正如我在之前关于另一个问题的评论交流中所说,这些类型的问题在摘要中并不能真正回答。您必须对客户端和服务器都有特定的要求,并且对正在交付的数据以及它在客户端上的紧急程度有特定的了解,因此需要特定的轮询间隔和特定的规模,以便开始进行一些计算或测试工具评估哪种方式可能是更理想的做事方式。变量太多,无法得出一个纯粹假设的答案。您必须定义一个场景,然后针对该特定场景分析不同的实现。

每秒请求数只是众多可能变量之一。例如,如果大多数时候您轮询实际上没有什么新东西,那么这给 SSE 案例带来了更多的优势,因为它根本没有任何事情可做(服务器上的零负载,除了一点点内存用于大部分时间都是打开的套接字),而轮询会产生持续的负载,即使无事可做。

服务器推送的第一个优势(无论是使用 SSE 还是 webSocket 实现)是服务器只需要在实际有相关数据发送到特定客户端时才对客户端执行任何操作。其余时间,套接字只是闲置在那里(可能偶尔会在很长的时间间隔内发送保持活动状态)。

轮询的第一个缺点是,客户端可能会多次轮询服务器,而服务器必须花费资源来处理轮询请求,只是为了通知客户端它没有任何新内容。

我们如何计算 Ajax 或 SSE 的极限频率在哪里?

这是一个相当复杂的过程。需要定义特定场景中的许多变量。它不像请求/秒那么简单。然后,您必须决定要测量或评估的内容以及规模? “服务器性能”是您唯一提到的内容,但这必须完全定义,并且必须将 CPU 使用率和内存使用率等不同因素加权到您正在测量或计算的任何内容中。然后,如果计算没有产生明显的答案,或者如果决策非常关键以至于您想使用真实指标验证计算,您甚至可能需要运行一些测试工具。

听起来您正在寻找“在大于 x 请求/分钟时,您应该使用轮询而不是 SSE”之类的答案,但我认为没有这么简单的答案。它取决于比 requests/min 或 requests/sec 更多的东西。

【讨论】:

好的,我知道在SSE中CPU不是问题,但是内存呢?假设每 5 秒有新数据(总是每 5 秒有新数据),如果服务器是 Apache+php,每个 SSE 连接将需要近 20MB,200 个用户一直是 4GB,每 5 秒只有 4GB 不是更好吗? @Enrique - 我认为 Apache+PHP 不适合用于持续数据传输。如果您为每个连接都启动一个 PHP 实例,那肯定不会。相反,您需要一个真正的服务器,除了套接字之外,每个连接都没有额外的开销。所以,如果这是一个 Apache+PHP 优化问题,那么更大的鱼就是 Apache+PHP。对于只接受传入套接字的真实服务器,每个新套接字的开销都非常小。您的问题根本没有提到 Apache+PHP。这就是你的问题所在。此类问题的技术错误。 @Enrique - 仅供参考,我对 webSockets 的所有经验都是使用 node.js,它特别擅长管理大量连接和大量非活动连接,因为它不使用线程进行连接。每个连接都有一个线程或进程的设计或环境对于扩展大量连接将是灾难性的。因此,首先,您必须选择正确的服务器架构来管理大量连接。 对一个无可救药的模糊问题的出色回答。最大的两条途径:Any kind of frequent polling is nearly always a costly choice.I don't think there is an answer that simple. It depends upon far more things than requests/min or requests/sec。另外:对于那些支持它的服务器,WebSockets 确实是一个很好的解决方案。【参考方案2】:

“轮询”会导致各方的开销。如果可以避免,请不要投票。

如果 SSE 是一个选项,它可能是一个不错的选择。 “这取决于”。

问:您的应用需要处理什么样的(如果有的话)“事件”?

【讨论】:

问题实际上是 SSE 与轮询的限制是什么。因为 SSE 需要为每个用户始终保持一个进程处于活动状态。如果我们需要频繁更新,这很好,但是这里的“频繁”是什么?每秒 1 次?每 5 秒? 20 秒不频繁,轮询更好? 哦 - 我以为你已经知道了。 SSE 的限制为42。但真正的问题在这里: 问:你有什么可以用作“事件”的东西,这样你就不必“投票”了吗?您希望被“通知”的究竟是什么“状态变化”? 可以是任何东西,例如假设您想更新某些股票的价格。如果您每秒钟更新一次,显然 SSE 是一个不错的选择,但如果您每分钟更新一次呢?无论如何使用 SSE 是个好主意吗?

以上是关于Ajax 轮询与 SSE(服务器端的性能)的主要内容,如果未能解决你的问题,请参考以下文章

ajax轮询与长轮询

轮询与 AsyncCallback 回调 - 慢速 Web 服务的最佳方法?

轮询与长轮询[关闭]

扩展聊天应用程序 - 短轮询与长轮询(AJAX、PHP)

数据实时可视化——实时交互(websocketSSE)

RocketMQ的技术亮点