当前位置: 首页 > article >正文

相比于WebSocket,SSE更适合轻量级

一、 前言

项目首页有一个待办任务数量和消息提醒数量的展示(单向数据的展示 ),之前使用了定时器,每隔十秒钟发送一次请求到后端接口拿数据,这也就是我们常说的轮询做法

1. 轮询的缺点

我们都知道轮询的缺点有几种:

资源浪费

  • 网络带宽:频繁的请求可能导致不必要的网络流量,增加带宽消耗。
  • 服务器负载:每次请求都需要服务器处理,即使是空返回,也会增加服务器的CPU和内存负载。

用户体验

  • 界面卡顿:频繁的请求和更新可能会造成用户界面的卡顿,影响用户体验。

2. websocket的缺点

那么有没有替代轮询的做法呢? 聪明的同学肯定会第一时间想到用websocket,但是在目前这个场景下我觉得使用websocket是显得有些笨重。我从以下这几方面对比:

  1. 客户端实现
    • WebSocket 客户端实现需要处理连接的建立、维护和关闭,以及可能的重连逻辑。
    • SSE 客户端实现相对简单,只需要处理接收数据和连接关闭。
  2. 适用场景
    • WebSocket 适用于需要双向通信的场景,如聊天应用、在线游戏等。
    • SSE 更适合单向数据推送的场景,如股票价格更新、新闻订阅等。
  3. 实现复杂性
    • WebSocket 是一种全双工通信协议,需要在客户端和服务器之间建立一个持久的连接,这涉及到更多的编程复杂性。
    • SSE 是单向通信协议,实现起来相对简单,只需要服务器向客户端推送数据。
  4. 浏览器支持
    • 尽管现代浏览器普遍支持 WebSocket,但 SSE 的支持更为广泛,包括一些较旧的浏览器版本。
  5. 服务器资源消耗
    • WebSocket 连接需要更多的服务器资源来维护,因为它们是全双工的,服务器需要监听来自客户端的消息。
    • SSE 连接通常是单向的,服务器只需要推送数据,减少了资源消耗。

二、 详细对比

对于这三者的详细区别,你可以参考下面我总结的表格:

以下是 WebSocket、轮询和 SSE 的对比表格:

特性WebSocket轮询PollingServer-Sent Events (SSE)
定义全双工通信协议,支持服务器和客户端之间的双向通信。客户端定期向服务器发送请求以检查更新。服务器向客户端推送数据的单向通信协议。
实时性高,服务器可以主动推送数据。低,依赖客户端定时请求。高,服务器可以主动推送数据。
开销相对较高,需要建立和维护持久连接。较低,但频繁请求可能导致高网络和服务器开销。相对较低,只需要一个HTTP连接,服务器推送数据。
浏览器支持现代浏览器支持,需要额外的库来支持旧浏览器。所有浏览器支持。现代浏览器支持良好,旧浏览器可能需要polyfill。
实现复杂性高,需要处理连接的建立、维护和关闭。低,只需定期发送请求。中等,只需要处理服务器推送的数据。
数据格式支持二进制和文本数据。通常为JSON或XML。仅支持文本数据,通常为JSON。
控制流客户端和服务器都可以控制消息发送。客户端控制请求发送频率。服务器完全控制数据推送。
安全性需要wss://(WebSocket Secure)来保证安全。需要https://来保证请求的安全。需要SSE通过HTTPS提供,以保证数据传输的安全。
适用场景需要双向交互的应用,如聊天室、实时游戏。适用于更新频率不高的场景,如轮询邮箱。适用于服务器到客户端的单向数据流,如股票价格更新。
跨域限制默认不支持跨域,需要服务器配置CORS。默认不支持跨域,需要服务器配置CORS。默认不支持跨域,需要服务器配置CORS。
重连机制客户端可以实现自动重连逻辑。需要客户端实现重连逻辑。客户端可以监听连接关闭并尝试重连。
服务器资源较高,因为需要维护持久连接。较低,但频繁的请求可能增加服务器负担。较低,只需要维护一个HTTP连接。

这个表格概括了 WebSocket、轮询和 SSE 在不同特性上的主要对比点。每种技术都有其适用的场景和限制,选择合适的技术需要根据具体的应用需求来决定。

三、 SSE(Server-Sent Events)介绍

我们先来简单了解一下什么是Server-Sent Events

Server-Sent Events (SSE) 是一种允许服务器主动向客户端浏览器推送数据的技术。它基于 HTTP 协议,但与传统的 HTTP 请求-响应模式不同,SSE 允许服务器在建立连接后,通过一个持久的连接不断地向客户端发送消息。

工作原理

  1. 建立连接
    • 客户端通过一个普通的 HTTP 请求订阅一个 SSE 端点。
    • 服务器响应这个请求,并保持连接打开,而不是像传统的 HTTP 响应那样关闭连接。
  2. 服务器推送消息
    • 一旦服务器端有新数据可以发送,它就会通过这个持久的连接向客户端发送一个事件。
    • 每个事件通常包含一个简单的文本数据流,遵循特定的格式。
  3. 客户端接收消息
    • 客户端监听服务器发送的事件,并在收到新数据时触发相应的处理程序。
  4. 连接管理
    • 如果连接由于任何原因中断,客户端可以自动尝试重新连接。

著名的计算机科学家林纳斯·托瓦兹(Linus Torvalds) 曾经说过:talk is cheap ,show me your code

我们直接上代码看看效果:

java代码

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;@RestController
@RequestMapping("platform/todo")
public class TodoSseController {private final ExecutorService executor = Executors.newCachedThreadPool();@GetMapping("/endpoint")public SseEmitter refresh(HttpServletRequest request) {final SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);executor.execute(() -> {try {while (true) { // 无限循环发送事件,直到连接关闭// 发送待办数量更新emitter.send(SseEmitter.event().data(5));// 等待5秒TimeUnit.SECONDS.sleep(5);}} catch (IOException e) {emitter.completeWithError(e);} catch (InterruptedException e) {// 当前线程被中断,结束连接Thread.currentThread().interrupt();emitter.complete();}});return emitter;}
}

前端代码

beforeCreate() {const eventSource = new EventSource('/platform/todo/endpoint');eventSource.onmessage = (event) => {console.log("evebt:",event)};eventSource.onerror = (error) => {console.error('SSE error:', error);eventSource.close();};this.$once('hook:beforeDestroy', () => {if (eventSource) {eventSource.close();}});},

改造后

客户端只发送了一次http请求,后续所有的返回结果都可以在event.data里面获取

总结

虽然 SSE(Server-Sent Events)因其简单性和实时性在某些场景下提供了显著的优势,比如在需要服务器向客户端单向推送数据时,它能够以较低的开销维持一个轻量级的连接,但 SSE 也存在一些局限性。例如,它不支持二进制数据传输,这对于需要传输图像、视频或复杂数据结构的应用来说可能是一个限制。此外,SSE 只支持文本格式的数据流,这可能限制了其在某些数据传输场景下的应用。还有,SSE 的兼容性虽然在现代浏览器中较好,但在一些旧版浏览器中可能需要额外的 polyfill 或者降级方案。

考虑到这些优缺点,我们在选择数据通信策略时,应该基于项目的具体需求和上下文来做出决策。如果项目需要双向通信或者传输二进制数据,WebSocket 可能是更合适的选择。

如果项目的数据更新频率不高,或者只需要客户端偶尔查询服务器状态,传统的轮询可能就足够了。

而对于需要服务器频繁更新客户端数据的场景,SSE 提供了一种高效的解决方案。

总之,选择最合适的技术堆栈需要综合考虑项目的需求、资源限制、用户体验和未来的可维护性。
=转载=

相关文章:

相比于WebSocket,SSE更适合轻量级

一、 前言 项目首页有一个待办任务数量和消息提醒数量的展示(单向数据的展示 ),之前使用了定时器,每隔十秒钟发送一次请求到后端接口拿数据,这也就是我们常说的轮询做法。 1. 轮询的缺点 我们都知道轮询的缺点有几种…...

项目2 数据可视化--- 第十五章 生成数据

数据分析是使用代码来探索数据内的规律和关联。 数据可视化是通过可视化表示来 探索和呈现数据集内的规律。 好的数据可视化,可以发现数据集中未知的规律和意义。 一个流行的工具是Matplotlib,他是一个数据绘图库; 还有Plotly包&#xff…...

【Maven私服配置】

Maven私服配置 对于一些中央的pom&#xff0c;应该配置对应的mirror镜像访问 <mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirr…...

QT (四)模型/视图 QFileSystemModel,QStringListModel,QStandardItemModel

思考&#xff1a;QTableWidget 在某种程度上可以等价为QStandardItemModel&#xff0c;同理&#xff0c;其他的功能也有类似的等价&#xff0c;但是以当前的QTableWidget 和QStandardItemModel为例的话&#xff0c;两者都是用于实现建立表格的相关组件&#xff0c;只不过QStand…...

BSD实现:单播

分用单播数据报 如果程序执行到这里&#xff0c;说明程序并没有执行多播操作&#xff0c;那么大概率是单播。 维护缓存指针 udp_last_inpcb是上一次接收数据报的端口的控制块指针&#xff0c;维护该指针的依据是许多程序往往具有时间局部性&#xff0c;也就是&#xff1a;经…...

. Unable to find a @SpringBootConfiguration(默认软件包中的 Spring Boot 应用程序)

解决&#xff1a; 新建一个包即可 问题&#xff1a; 默认软件包中的 Spring Boot 应用程序。 原因&#xff1a; 默认包的定义 &#xff1a; 如果一个 Java 类没有使用 package 声明包名&#xff0c;则该类会被放置在默认包中。Spring Boot 遵循 Java 的包管理约定&#xff…...

【前端知识】浏览器兼容方案polyfill

浏览器兼容方案polyfill 什么是 Polyfill&#xff1f;Polyfill 的作用Polyfill 的工作原理1. **特性检测**2. **加载 Polyfill**3. **模拟实现** Polyfill 的常见场景Polyfill 的使用方式Polyfill 的优缺点优点缺点 常见的 Polyfill 库总结 什么是 Polyfill&#xff1f; Polyf…...

互信息的定义与公式

互信息 定义公式 从条件熵中我们知道&#xff0c;当获取的信息和要研究的食物”有关系时“&#xff0c;这些信息才能帮助我们消除不确定性。如何衡量获取信息和要研究事物“有关系”呢&#xff1f;比如常识告诉我们&#xff0c;一个随机事件“今天深圳下雨”和另一个随机事件“…...

(算法基础——树)——python树结构使用指南

1. 树的定义与实现 树是一种非线性数据结构&#xff0c;常用于解决层次化数据问题&#xff08;如路径搜索、二叉树遍历等&#xff09;。以下是树的两种常见实现方式&#xff1a; (1) 类&#xff08;Class&#xff09;实现 class TreeNode:def __init__(self, val0, leftNone…...

【小白学AI系列】NLP 核心知识点(七)Embedding概念介绍

Embedding&#xff08;嵌入&#xff09; 是自然语言处理&#xff08;NLP&#xff09;中非常重要的概念。简单来说&#xff0c;embedding 是一种将离散的、稀疏的、不可直接计算的对象&#xff08;比如词、字符或句子&#xff09;转换为 密集的、连续的向量表示 的技术。 这个向…...

Android adb测试常用命令大全

目录 一、查看最上层成activity名字: 二、查看Activity的任务栈&#xff1a; 三、获取安装包信息 四、性能相关 1、显示CPU信息 : 2、查看CPU使用信息 3、内存信息&#xff08;meminfo package_name or pid 使用程序的包名或者进程id显示内存信息&#xff09; 4、电量信…...

FRRouting配置与OSPF介绍,配置,命令,bfd算法:

文章目录 1、frrouting的配置&#xff1a;2、ospf2.1、检测和维护邻居关系2.2、ospfDR和BDR2.3、odpf邻居表2.4、ospf常用命令2.5、bfd配置 1、frrouting的配置&#xff1a; sudo service zebra start sudo service ospfd start telnet localhost 2604 en configure termina…...

【MyBatis】预编译SQL与即时SQL

目录 1. 以基本类型参数为例测试#{ }与${ }传递参数的区别 1.1 参数为Integer类型 1.2 参数为String类型 2. 使用#{ }传参存在的问题 2.1 参数为排序方式 2.2 模糊查询 3. 使用${ }传参存在的问题 3.1 SQL注入 3.2 对比#{ } 与 ${ }在SQL注入方面存在的问题 3.3 预编译…...

prometheus、grafana、windows、node exporter 安装包

开发过程中应用到的安装包软件&#xff1a; prometheus-2.20.0.windows-amd64.tar.gz windows_exporter-0.13.0-amd64.exe grafanawindows-x64.zip influxdb-1.7.0_windows_amd64.zip 我用夸克网盘分享了「prometheus、grafana、windows、node exporter 安装包」&#xff…...

Python数据可视化 - Matplotlib教程

文章目录 前言一、Matplotlib简介及安装1. Matplotlib简介2. 安装Matplotlib 二、Matplotlib Pyplot1. Pyplot介绍2. Pyplot中方法介绍2.1 创建和管理图形2.2 绘制图形2.3 设置图形属性2.4 保存和展示 三、Matplotlib绘图标记1. 介绍2. 基本用法3. 标记大小与颜色4. 标记样式列…...

DeepSeek R1 与 OpenAI O1:机器学习模型的巅峰对决

我的个人主页 我的专栏&#xff1a;人工智能领域、java-数据结构、Javase、C语言&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;点赞&#x1f44d;收藏❤ 一、引言 在机器学习的广袤天地中&#xff0c;大型语言模型&#xff08;LLM&#xff09;无疑是最…...

内容中台重构企业内容管理流程驱动智能协作升级

内容概要 内容中台作为企业数字化转型的核心基础设施&#xff0c;通过技术架构革新与功能模块整合&#xff0c;重构了传统内容管理流程的底层逻辑。其核心价值在于构建动态化、智能化的内容生产与流转体系&#xff0c;将分散的创作、存储、审核及分发环节纳入统一平台管理。基…...

STM32 Flash详解教程文章

目录 Flash基本概念理解 Flash编程接口FPEC Flash擦除/写入流程图 Flash选项字节基本概念理解 Flash电子签名 函数读取地址下存放的数据 Flash的数据处理限制部分 编写不易&#xff0c;请勿搬运&#xff0c;感谢理解&#xff01;&#xff01;&#xff01; Flash基本概念…...

小米 R3G 路由器刷机教程(Pandavan)

小米 R3G 路由器刷机教程&#xff08;Pandavan&#xff09; 一、前言 小米 R3G 路由器以其高性价比和稳定的性能备受用户青睐。然而&#xff0c;原厂固件的功能相对有限&#xff0c;难以满足高级用户的个性化需求。刷机不仅可以解锁路由器的潜能&#xff0c;还能通过第三方固…...

红队视角出发的k8s敏感信息收集——Kubernetes API 扩展与未授权访问

针对 Kubernetes API 扩展与未授权访问 的详细攻击视角分析&#xff0c;聚焦 Custom Resource Definitions (CRD) 和 Aggregated API Servers 的潜在攻击面及利用方法&#xff1a; ​ 攻击链示例 1. 攻击者通过 ServiceAccount Token 访问集群 → 2. 枚举 CRD 发现数据库配…...

11. Docker 微服务实战(将项目打包生成镜像,在 Docker 当中作为容器实例运行)

11. Docker 微服务实战(将项目打包生成镜像&#xff0c;在 Docker 当中作为容器实例运行) 文章目录 11. Docker 微服务实战(将项目打包生成镜像&#xff0c;在 Docker 当中作为容器实例运行)2. 最后&#xff1a; 建 Module - docker_boot 编辑 pom <?xml version"1.0&…...

mysql和minio

在现代应用架构中&#xff0c;Word 文档、PPT 等文件通常存储在对象存储服务&#xff08;如 MinIO&#xff09;中&#xff0c;而不是直接存储在关系型数据库&#xff08;如 MySQL&#xff09;中。以下是具体的分工和原因&#xff1a; 为什么选择对象存储&#xff08;如 MinIO&a…...

计算机视觉:卷积神经网络(CNN)基本概念(二)

第一章&#xff1a;计算机视觉中图像的基础认知 第二章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(一) 第三章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(二) 第四章&#xff1a;搭建一个经典的LeNet5神经网络 接上一篇《计算机视觉&am…...

【数据结构-红黑树】

文章目录 红黑树红黑树介绍红黑树的五个基本性质红黑树的平衡原理红黑树的操作红黑树的操作 代码实现节点实现插入和查询操作 红黑树 红黑树介绍 红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡的二叉查找树&#xff08;Binary Search Tree, BST&#xff09;&…...

dify.ai 配置链接到阿里云百练等云厂商的 DeepSeek 模型

要将 dify.ai 配置链接到阿里云百练等云厂商的 DeepSeek 模型. 申请阿里云百练的KEY 添加模型 测试模型...

手机ROM是什么

本篇将以我自己的手机——小米13为例 手机 ROM 详解 在手机领域&#xff0c;ROM&#xff08;Read-Only Memory&#xff09; 通常指的是 手机的操作系统和固件&#xff0c;包括 Android 设备的 系统镜像&#xff08;system.img&#xff09;、引导程序&#xff08;boot.img&…...

应用分层、三层架构和MVC架构

前言 在前面中&#xff0c;我们已经学习了Spring MVC 的一些基础操作&#xff0c;那么后面就用一些简单的案例来巩固一下。 在开始学习做案例之前&#xff0c;我们先来了解一下在软件开发中常见的设计模式和架构。 应用分层 含义 应用分层是一种软件开发设计思想&#xff0…...

Apache Struts2 - 任意文件上传漏洞 - CVE-2024-53677

0x01&#xff1a;漏洞简介 Apache Struts 是美国 Apache 基金会的一个开源项目&#xff0c;是一套用于创建企业级 Java Web 应用的开源 MVC 框架&#xff08;将软件分为模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controller&a…...

传统混合专家模型MoE架构详解以及python示例(DeepSeek-V3之基础)

我们已经了解到DeepSeek-V3的框架结构基于三大核心技术构建:多头潜在注意力(MLA)、DeepSeekMoE架构和多token预测(MTP)。而DeepSeekMoE架构的底层模型采用了混合专家模型(Mixture of Experts,MoE)架构。所以我们先了解一下传统混合专家模型MoE架构。 一、传统混合专家模…...

Tomcat如何处理Http请求

Tomcat处理HTTP请求的流程是一个复杂但有序的过程&#xff0c;涉及多个组件的协同工作。以下是对Tomcat处理HTTP请求流程的详细讲解&#xff1a; 一、接收请求 监听端口&#xff1a;Tomcat通过配置的Connector组件监听特定的端口&#xff08;默认是8080&#xff09;&#xff…...