如何使用 Server-Sent Events 实现可伸缩的实时新闻推送系统?

在现代 Web 应用程序中,实时数据的需求日益增长。传统的轮询和长轮询方法已经无法满足业务需求,因为它们惊人地浪费了带宽和服务器资源。而 Server-Sent Events(简称 SSE)因为易于使用、可伸缩性和更稳定的连接,成为了很多公司选择实现实时通信的首选。

在本文中,我将介绍 Server-Sent Events 的基础知识和如何使用 SSE 实现可伸缩的实时新闻推送系统。首先,我们将讨论什么是 SSE,然后介绍 SSE 的工作原理和如何实现一个 SSE 服务器。然后,我们将通过一个简单的新闻推送示例来演示如何在前端使用 SSE。最后,我们将探讨如何在 SSE 服务器上方实现负载均衡和扩展。

什么是 Server-Sent Events?

Server-Sent Events 是一种 HTML5 API,用于在客户端通过浏览器获取实时更新的数据。它们构建在 HTTP 上,使用纯文本(而不是二进制)的无状态流来传输数据。

SSE 的主要优点是它们异步、可靠和可伸缩。初始化 SSE 连接只需要一次 HTTP 请求,然后服务器可以向客户端发送事件数据。这可以减少网络延迟和减小带宽的使用。

另一个好处是 SSE 服务器可以通过发送专用的“保持活动”消息来确保 SSE 连接保持活动状态,这样客户端就可以随时接收数据。这使 SSE 更稳定和可靠,即使在较差的网络连接下也能正常工作。

如何使用 SSE?

SSE 服务器端的实现

要实现 SSE 服务器,我们需要添加一些特殊的 HTTP 标头,并使用 event-stream 格式给客户端发送数据。下面是一个简单 SSE 服务器示例:

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

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

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

这个示例使用 http 模块创建了一个 SSE 服务器。在响应中,我们设置了 Content-Typetext/event-stream,这是 SSE 的 MIME 类型,表示将使用 SSE 传输格式。同时我们也设置了 Cache-Controlno-cache,这样浏览器就会注意到数据的即时性。我们通过设置 Connectionkeep-alive,表示需要在一个长连接上完成传输。

在服务器中,我们使用 setInterval() 每秒钟发送一个事件数据。每个事件数据包含了一个数据行以及一个两个 \n 换行符,表示一个事件的结束。

SSE 客户端的实现

在 SSE 客户端中,我们只需要使用 EventSource 对象来初始化 SSE 连接并通过 onmessage 回调处理数据的接收。下面是一个示例:

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

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

EventSource 对象的构造函数中,我们传入了 SSE 服务器地址,并为每个事件定义了一个处理函数。每当服务器发送一个新的事件数据,onmessage 回调函数会被调用,并通过 event.data 属性获取这个事件的数据。在这个示例中,我们将事件消息写入浏览器的控制台。

新闻推送示例

为了演示 SSE 的使用,我们将开发一个简单的实时新闻推送示例。该应用将定期从服务器接收新闻更新,并将新的文章显示在客户端。为了实现这个功能,我们需要编写一个 SSE 发布服务器,然后在前端创建 SSE 订阅客户端。下面是代码示例。

SSE 服务器端

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

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

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

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

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

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

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

为了模拟一个实际场景,我们将从文件加载新闻数据。我们将在每次连接后,定期向客户端发布新的新闻数据。在 SSE 事件的 event: 字段中,我们定义了一个 news-update 事件名称。在 data: 字段中,我们将新闻数据作为 JSON 字符串发布。注意,在 data: 字段及其前面的行末尾必须有两个 \n 换行符才能表示事件结束。

SSE 客户端

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

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

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

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

一个客户端通过 EventSource() 函数创建一个 SSE 连接,并为事件 news-update 添加了事件处理程序来更新新闻列表。在事件回调中,所有发布的新闻数据都将用 JavaScript 对象表示,并使用 ul 列表在客户端的页面上进行展示。这个示例的结果如下图所示:

如何扩展 SSE 服务器

当收到大量的 SSE 连接时,单个 SSE 服务器可能无法处理所有连接。我们通常需要通过许多服务器将客户端连接均衡到多个 SUES 服务器上。下面是一个配置负载均衡器的示例代码:

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

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

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

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

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

在这个示例中,我们使用 cluster 模块来管理多个 SSE 服务器。主进程负责创建 Worker 进程,并在子进程中创建 SSE 服务器。当其中任一子进程退出时,主进程会重新创建一个新的进程(以保持 worker 数量的恒定),以确保我们的 SSE 服务器始终可以响应客户端连接。

总结

在本文中,我们了解了 SSE 的基础知识和如何使用 SSE 实现可伸缩的实时新闻推送系统。我们在服务器和客户端上都展示了一个 SSE 示例,以及如何使用负载均衡器来弥补多个服务器的需求。

当然,还有很多其他的使用 SSE 的场景,如实时聊天应用程序、仪表盘、股票报价等。SSE 适用于任何实时通信的场景,它可以让我们的应用程序更可靠、可伸缩,并减少带宽的使用。

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/64880bc248841e989468d5fc


猜你喜欢

  • 基于 Server-Sent Events 实现 HTML5 实时聊天室

    随着 Web 技术的不断发展,实时通信的需求越来越大。传统的 HTTP 请求响应模式无法满足实时通信的需求,因此 HTML5 引入了一种新的通信协议,即 Server-Sent Events(SSE)...

    1 年前
  • 在 Node.js 项目中使用 Enzyme 进行单元测试

    在开发 Node.js 项目时,单元测试是非常重要的一步。单元测试可以帮助我们保证代码的质量,及时发现和修复潜在的问题,提高代码的可维护性和可扩展性。 在本文中,我们将介绍如何在 Node.js 项目...

    1 年前
  • koa 中使用 Redis 作为 session 存储

    在 Web 应用开发中,session 是保持用户状态的一种常用方法。koa 框架默认提供了基于内存的 session 存储,但随着用户量的增加,这种方式已经无法满足性能需求。

    1 年前
  • Node.js 中如何实现文件上传和下载?

    在 Web 应用程序的开发中,文件上传和下载是一项非常重要的功能,它能够为用户提供方便快捷的文件传输方式。Node.js 作为一种服务器端的技术,也能够提供文件上传和下载的服务,本文将介绍如何在 No...

    1 年前
  • 如何在 LESS 中实现基于 BEM 规范的样式命名

    在前端开发中,CSS 是我们进行页面样式定义的一种语言,但是在大型项目中,如果样式命名混乱,样式重复、嵌套等问题可能会大大影响开发效率和后期维护性,因此采用 BEM 规范来定义样式命名是一个很好的选择...

    1 年前
  • Mongoose 中的 Schema Types 使用详解

    在使用 Mongoose 构建 MongoDB 数据库时,我们需要使用 mongoose.Schema() 创建 schema(数据表结构),其中需要指定每个字段的类型。

    1 年前
  • Redis 的事务机制详解

    前言 Redis 是当下最流行的内存键值存储数据库,因为性能高、可扩展性好、可靠性高等众多优点而受到了广泛的关注和使用。Redis 的事务机制是 Redis 的一个重要特性之一,本文将重点介绍 Red...

    1 年前
  • 使用 Mocha 测试 React 组件的断言优化

    前端开发中,测试是非常重要的一环。在 React 组件开发中,使用 Mocha 进行单元测试是很常见的。Mocha 是一个 JavaScript 测试框架,可以实现用于测试前端代码的性能及可靠性。

    1 年前
  • Socket.io 如何使用 Https 协议进行数据传输

    介绍 Socket.io 是一个开源的 JavaScript 库,它实现了实时、双向、事件驱动的数据传输。它是基于 WebSockets 技术实现的, 并能够兼容旧版的浏览器和环境。

    1 年前
  • 如何优雅地对 RESTful API 进行日志管理

    在前端类应用中,我们常常需要与后端交互获取数据,RESTful API 是常见的一种交互方式,但在使用时,我们可能会遇到一些问题,比如如何处理日志管理。本文将详细讨论如何优雅地对 RESTful AP...

    1 年前
  • 使用 Webpack 优化 Custom Elements 的构建和部署

    在现代化的 Web 应用程序中,Custom Elements 是创建可重用的 Web 组件的一种流行方式。但是,Custom Elements 的构建和部署过程可能会变得复杂和困难。

    1 年前
  • ES6 中的模板字符串,如何方便取代传统的拼接方式

    在前端开发中,字符串的拼接是比较常见的操作。在 JavaScript 传统的拼接方式中,我们通常使用 + 或者 join() 方法来实现字符串的拼接。但是这些方式有一个明显的缺陷,就是不够直观和易读。

    1 年前
  • ES9 中的新特性:Object.fromEntries() 方法详解

    在 ES9 中新增了一个非常实用的方法 Object.fromEntries()。这个方法可以将一个键值对数组转换为对象。这个方法可以使我们在前端开发中更加便捷地处理数据。

    1 年前
  • Fastify 中的跨域请求处理方法

    前言 在 Web 开发中,跨域请求是常常遇到的问题。一般情况下,我们都需要在后端处理跨域请求,但是使用 Fastify 可以很方便的在前端解决跨域问题,从而提高网站的性能和响应速度。

    1 年前
  • Docker 和虚拟机的比较

    1. 背景介绍 随着云计算和容器技术的发展,Docker 和虚拟机成为了近些年来最常用的两种部署应用程序的方式。虚拟化技术是将一台物理机划分成多个虚拟机,每个虚拟机都可以运行一个完整的操作系统和应用程...

    1 年前
  • MongoDB 如何实现文档中日期字段的筛选?

    MongoDB 是一种流行的 NoSQL 数据库,它支持多种数据类型,包括日期数据类型。在实际开发中,我们经常需要对 MongoDB 中的文档进行日期筛选操作。本文将介绍 MongoDB 如何实现文档...

    1 年前
  • Angular 应用中如何使用 RxJS

    RxJS 是一个非常强大的 JavaScript 库,它为开发者提供了一套响应式编程的工具和理念。在 Angular 应用中使用 RxJS 可以让我们更加高效地处理异步数据流,处理网络请求、用户输入等...

    1 年前
  • 如何在 Webpack 中使用 Vue 模板

    在前端开发中,Vue.js 已经成为了一种非常流行和实用的框架。而在 Webpack 中使用 Vue 模板也是非常常见的做法。这篇文章将会介绍如何在 Webpack 中使用 Vue 模板。

    1 年前
  • ECMAScript 2017 中 Object.values() 方法的使用实例

    前言 JavaScript 的不断更新促使其日益优秀,ECMAScript2017 中 Object.values() 方法是 ECMAScript2015 中 Object.getOwnProper...

    1 年前
  • Vue SPA 开发中的性能优化技巧

    Vue 是现代化的 JavaScript 前端框架之一,被广泛地应用于单页应用程序(SPA)的开发中。尽管 Vue 具有灵活性和易用性等优点,但是 SPA 应用程序通常在代码维护和性能方面带来挑战。

    1 年前

相关推荐

    暂无文章