SSE 在大型系统中如何支持高并发

前言

在现代 Web 开发中,实时通信已经成为了一种非常重要的技术。随着用户的数量增加,系统的并发量也会逐渐增加。这时候,一些实时通信技术就会被引入,SSE 就是其中一种。

SSE(Server-Sent Events)是一种基于 HTTP 协议的服务器推送技术,在前端应用中得到了广泛的应用,比如在线聊天室、股票行情等实时更新的应用场景。SSE 从服务器向客户端发送单向实时数据流,通过持久连接的技术,实现了服务器对客户端的主动通知,将更快地向前端推送实时数据。

本文将会探讨如何在大型系统中,使用 SSE 技术来支持高并发。

SSE 的优势

相比其他实时通信技术,SSE 有以下几个优势:

  1. SSE 是基于已有的 HTTP 协议而构建的,不需要额外开启端口或协议,对服务器端架构无任何要求,转发和代理等方式都通用;
  2. SSE 可以保持长连接,从而避免 HTTP 报头和链接的开销,减轻服务器压力;
  3. SSE 提供了更加灵活、简洁的消息格式,从而可以避免一些繁琐的 JSON 报文解析工作;
  4. SSE 可以回传文本、JSON 以及二进制文件,具有很好的扩展性。

SSE 的实现原理

在 SSE 的实现中,服务器将数据封装成特定格式的消息(通常是文本格式),通过已经建立好的连接将消息一次次地推送给客户端。这里的连接并不是长时间保持不断的,而是保持一定时间(建议为一分钟以内)然后在客户端断开连接后,服务器在一定时间内重新建立连接,从而推送新的消息。

客户端在接收到数据后,需要通过 JavaScript 处理,根据消息类型更新页面相关展示。

SSE 主要由以下那三个部分组成:

  1. 事件类型:事件类型是一个关键字,用于告诉浏览器该事件的类型。在浏览器端,可以使用 onmessage() 事件处理程序来监听该事件。
  2. 数据:是推送到浏览器的消息正文,是一个字符串,可以用文本、JSON、XML等格式来传递。
  3. 回退重连时间:告诉浏览器执行连接失败时的连接重试的功能,在没有指定的情况下,浏览器会在三秒钟后自动重连。

SSE 超出并发的问题

在大型系统中,当并发量超过一定限制时,SSE 技术也可能会出现一些问题:

  1. 浏览器硬件环境的限制:每个浏览器在处理文本、JavaScript 等资源时都存在一定的瓶颈,当服务器向浏览器发送大量 SSE 数据时,可能会导致浏览器无法承受超过一定量的 SSE 数据。
  2. 服务器的潜在问题:SSE 技术中的持久连接,也给服务器带来了压力,如果服务器无法承受大量的长连接或高并发,可能导致服务器崩溃或性能下降。

针对以上问题,以下是一些针对大型系统的 SSE 最佳实践:

SSE 通信模型

为了解决 SSE 通信模型的问题,我们可以使用分布式服务器的方式进行实现。将不同的消息推送到不同的服务器,并跟踪每个客户端从何处接收其消息。这个通信模型主要由三个部分组成:

  1. 数据源:数据源组件是服务器或服务,它生成更新并将其推送到消息服务器。
  2. 消息服务器:经过中间件展现的消息服务器,维护客户端和数据源之间的联系,并负责将数据推送到正确的客户端。如果到客户端的连接断开,消息服务器会根据需要重新连接,这时数据源就可以推送新的数据。
  3. 客户端:客户端需要连接到消息服务器,以便能够准确地接收消息,必要时重新连接。

SSE 广播优化

在实践中,我们需要对 SSE 的广播进行优化。可以将广播分成三类,不同类别的广播有不同的优化方案。

广播类型一:基于全选字段广播

基于全选字段广播可以使用策略来避免重复发送广播。即服务器端根据现有数据界面检查广播是否需要发送,只有在需要发送广播的情况下才会向客户端发送数据。

广播类型二:选择性广播

更为复杂的广播可以使用有选择性的方法,服务器不将广播发往所有客户端,而是仅针对指定的客户端进行广播。这种广播的好处在于,可以避免服务器向未连接的客户端发送广播。

广播类型三:实时广播

实时广播主要针对非常实时的广播。这种广播方式要求服务器向客户端发送最新数据,因此可以使用 Delta 或 Diff 消息等技术来减少传输的数据量,提高传输速率。

示例代码

以下是一个使用 SSE 技术实现的聊天室示例代码:

服务端代码:

----- ---- - ----------------
----- -- - --------------
----- --- - ---------------
----- ----------- - -----------------------
----- ----- - ---------------
---
 - ---------
 - -----------------------
 --
----- --------
    --------------
        --------------- - ---
    -
    ----
    -----------
        --------------------------
            -------------------- - ---
        -
        ------------------------------
    -
    ------
    ------------
        --- -------- - ---------------------
        --- ----- - ---------------------
        -------------------------
    -
    ----
    ------------------
        --- --------- - ---------------------
        --------------
            -------------------------- ---
                ----------------------------
            ---
        -
    -
-
-- -------
--- ---------- - ------------------------------
    --- ---------- - -------------------
    --- -
        -----------------
            -- -------
            ---- ----
                ---------------------------------------------
                ------
            -- ----
            ---- -----------
                --- ------ - ---
                ------------------- -- --------------------
                ------------------
                    --- ------------------ - ------------------------------

                    ----------------------------------------------------------------
                    -------------------
                ---
                ------
            -- -----
            ---- -------------
                --- -- - ------
                -------------------
                    -----------------------------------
                    ---------------------------
                    -------------------------
                ---
                --- -------- - --- ---
                    --- ---- - --------------------
                    -------------------------------------------------------
                -
                --------------------------------
                -------------------------------
                    ---------------------------------
                ---
                ------
            --------
                ------------ --- ---- --------------
                ------
        -
    - ----- ------- -
        --------------- ------ -----------
    -
---
----- -------- - --- ----------
------------------------

客户端代码:

------    
    ------ 
        --------
            -------- ----------
                --- ------- - -----------------------------------------------
                --- -------- - ------------------------------------------------

                ------------------
                    --------------
                    ---------
                        ---------------------------------
                    --
                    ----- ----------------
                        ----------------
                    --
                ---------------- ---
                    ------------------ --- -----
                        ---------------------------------------------- - ---
                    -
                --
            -

            --- -----------  - --- --------------------------
            --------------------- - ----
                --- ------- - -------------------
                --- --------- - ---------------------------------------------
                --- -- - -----------------------------
                ------------ - -----------------------------------------
                --------------------------
            -
        ---------  
    -------
    ------
        ------------
        --- ----------------------------
        ---- ---------------------
            ------ ------------------- ------------
            ------ ------------------ ------------
            ------- -------------------------------
        ------
    -------
-------   

结论

通过实践,我们可以发现,在大型系统中,SSE 技术可以通过增加服务器负载和优化 SSE 广播等方式来有效地支持高并发。同时,SSE 技术可扩展和灵活,可以适用于很多实时通信开发场景。

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