如何处理 Server-sent Events 中的连接数过高问题

随着 Web 应用程序的不断增长,使用服务器发送事件(Server-sent Events, SSE)成为了许多开发人员的首选解决方案,因为 SSE 允许服务器在客户端请求的情况下主动将数据推送到客户端,而不需要客户端不断地轮询服务器。然而,当客户端数量增加时,连接数的问题可能会出现。如果不适当处理,连接数过高可能会对服务器造成负面影响,导致服务器性能不佳或者崩溃。本文将介绍如何在 SSE 中处理连接数过高的问题。

问题根源

当客户端连接服务器并请求 SSE 事件时,它们会保持该连接打开并等待服务器推送数据。在直到服务器发送数据之前,这些连接都将保持打开状态并占用一些服务器资源。如果客户端数量增加,尤其是在较短的时间内,打开的连接数量会快速增加,导致服务器性能受到影响。

解决方案

1. 使用心跳检测

使用心跳检测可以帮助查找闲置连接,尤其是在客户端无法触发 onClose 事件时。可将连接标记为“已死”,并在一段时间后关闭连接。

以下是一个用于检测 SSE 已死连接的示例代码:

const SSE_KEEP_ALIVE_INTERVAL = 30000 // 30 seconds
const clients = []

function sendSSE(res) {
  const client = { res }
  clients.push(client)
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  })
  
  const intervalId = setInterval(() => {
    res.write(':keep-alive\n\n')
  }, SSE_KEEP_ALIVE_INTERVAL)
  
  req.on('close', () => {
    clearInterval(intervalId)
    clients.splice(clients.indexOf(client), 1)
  })
}

function cleanupDeadConnections() {
  const now = Date.now()
  clients
    .filter((client) => now - client.lastSeen > SSE_KEEP_ALIVE_INTERVAL * 2)
    .forEach((client) => {
      client.res.end()
      clearInterval(client.intervalId)
      clients.splice(clients.indexOf(client), 1)
    })
}
setInterval(cleanupDeadConnections, SSE_KEEP_ALIVE_INTERVAL)

2. 使用反向代理

将 SSE 流放在单独的域上,或将其嵌入到其他已存在的流中,以便可以使用反向代理工具来优化连接。

反向代理应该能够智能地将客户端导向可用的 SSE 域,从而降低对所有域的连接数量。此外,反向代理还可以实现该域的负载平衡和故障转移。

3. 使用 WebSocket

WebSocket 相较于 SSE 更为高效。WebSocket 支持双向通信,可以在单个连接上发送和接收多个消息。WebSocket 适合于任何需要双向通信的应用程序,如在线游戏、聊天应用程序等等。

以下是一个用于 SSE 到 WebSocket 的转换示例代码:

const SSEStream = require('ssestream')
const WebSocket = require('ws')

const wss = new WebSocket.Server({ port: 8080 })

wss.on('connection', (ws) => {
  const sse = new SSEStream(ws)
  const { push } = sse
  
  SSEStream.createEventSource({
    path: 'sse',
    stream: sse,
    keepAlive: true,
    retry: 10000
  })

  ws.on('message', (data) => {
    // handle incoming data
  })

  ws.on('close', () => {
    // handle close event
  })
})

总结

本文介绍了如何在 SSE 中处理连接数过高的问题,通过使用心跳检测、反向代理和 WebSocket 转换等方法来降低连接数并提高服务器性能。希望本文的内容能够对开发人员理解 SSE 的连接问题,并提供一些可行的解决方案。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65935dd8eb4cecbf2d80f256


纠错反馈