长轮询

admin1年前 (2023-07-29)it知识219

长轮询是与服务器保持持久连接的最简单的方式,它不使用任何特定的协议,例如 WebSocket 或者 Server Sent Event。

它很容易实现,在很多场景下也很好用。

从服务器获取新信息的最简单的方式是定期轮询。也就是说,定期向服务器发出请求:“你好,我在这儿,你有关于我的任何信息吗?”例如,每 10 秒一次。

作为响应,服务器首先通知自己,客户端处于在线状态,然后 —— 发送目前为止的消息包。

这可行,但是也有些缺点:

  1. 消息传递的延迟最多为 10 秒(两个请求之间)。

  2. 即使没有消息,服务器也会每隔 10 秒被请求轰炸一次,即使用户切换到其他地方或者处于休眠状态,也是如此。就性能而言,这是一个很大的负担。

因此,如果我们讨论的是一个非常小的服务,那么这种方式可能可行,但总的来说,它需要改进。

长轮询

所谓“长轮询”是轮询服务器的一种更好的方式。

它也很容易实现,并且可以无延迟地传递消息。

其流程为:

  1. 请求发送到服务器。

  2. 服务器在有消息之前不会关闭连接。

  3. 当消息出现时 —— 服务器将对其请求作出响应。

  4. 浏览器立即发出一个新的请求。

对于此方法,浏览器发出一个请求并与服务器之间建立起一个挂起的(pending)连接的情况是标准的。仅在有消息被传递时,才会重新建立连接。

long-polling.svg

如果连接丢失,可能是因为网络错误,浏览器会立即发送一个新请求。

实现长轮询的客户端 subscribe 函数的示例代码:

async function subscribe()
{
let response = await fetch("/subscribe");
if(response.status == 502){
// 状态 502 是连接超时错误,
    
// 连接挂起时间过长时可能会发生,
    
// 远程服务器或代理会关闭它
    
// 让我们重新连接
    
await subscribe();
} else if(response.status != 200)
{    
// 一个 error —— 让我们显示它    
showMessage(response.statusText);    
// 一秒后重新连接    
await new Promise(resolve=> setTimeout(resolve,1000));    
await subscribe();  
}else{    
// 获取并显示消息   
let message =await response.text();
showMessage(message);    
// 再次调用 subscribe() 以获取下一条消息    
await subscribe();
}
}
subscribe();

正如你所看到的,subscribe 函数发起了一个 fetch,然后等待响应,处理它,并再次调用自身。

服务器架构必须能够处理许多挂起的连接。

某些服务器架构是每个连接对应一个进程,导致进程数和连接数一样多,而每个进程都会消耗相当多的内存。因此,过多的连接会消耗掉全部内存。

使用像 PHP 和 Ruby 语言编写的后端程序会经常遇到这个问题。

使用 Node.js 编写的服务端程序通常不会出现此类问题。

也就是说,这不是编程语言的问题。大多数现代编程语言,包括 PHP 和 Ruby,都允许实现更适当的后端程序。只是请确保你的服务器架构在同时有很多连接的情况下能够正常工作。

在消息很少的情况下,长轮询很有效。

如果消息比较频繁,那么上面描绘的请求-接收(requesting-receiving)消息的图表就会变成锯状状(saw-like)。

每个消息都是一个单独的请求,并带有 header,身份验证开销(authentication overhead)等。

因此,在这种情况下,首选另一种方法,例如:Websocket 或 Server Sent Events。


标签: JavaScript

相关文章

javascript字符串方法和属性

javascript字符串方法和属性1.获取字符串的长度var text=""abcndfsdfdsfsd"; console.log(text.length...

JavaScript 数组排序

sort() 方法以字母顺序进行排序var  fruits = ["banana", "orange",&qu...

electorn是什么

关于electron有以下信息:Electron 是一款可以使用 JavaScript、HTML 和 CSS 来构建跨平台桌面应用程序的开源框架,它可以让开发者使用 web 技术来创建原生应用程序。E...

Vue 报错error:0308010C:digital envelope routines::unsupported 解决方案

Error: error:0308010C:digital envelope routines::unsupported出现这个错误是因为 node.js V17版本中最近发布的OpenSSL3.0,...

javascript的重要性

JavaScript在编程中具有以下重要性:前端开发:JavaScript是Web前端开发的基础语言,用于创建动态交互性和用户界面。它可以直接在浏览器中运行,使得开发者可以快速构建和部署Web应用程序...

JavaScript可以应用在哪些领域?

JavaScript的应用领域非常广泛,包括但不限于以下领域:网站开发:这是JavaScript最常用的领域之一,可以用于实现前端逻辑、动态特效、表单验证、导航栏、交互性等功能。移动开发:通过结合HT...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。