简单实现服务端实时推送消息

最近工作中这样一个需求,在商城首页需要实时展示每个品类商品的成交量,大致效果(滚动效果)如下所示:

相信很多小伙伴一收到这个需求,立马就会想到客户端需要实时获取服务端消息,本文就主要介绍一种简单实现方案

Server-Sent Events

Server-Sent Events(SSE) , 是一种服务器端到客户端(浏览器)的单项消息推送 SSE 它是基于HTTP协议的,我们知道一般意义上的HTTP协议是客户端发起请求,服务端响应。但SSE是个例外,允许服务器在任何时候将数据推送到连接的客户端,而不需要客户端发起请求

SpringBoot实现SSE服务端示例

在我们平常使用的 SpringBoot 中,里面有个 SseEmitter 类已经封装好了相关操作,我们通过该类就可以实现SSE功能。

java 复制代码
@Slf4j
@Service
public class ServerSentEventsClient {

    private final static Map<String, SseEmitter> sseEmitterMap = new ConcurrentHashMap<>();

    public SseEmitter connect(String userId) {
        // 设置超时时间,0表示不过期。默认30秒
        SseEmitter sseEmitter = new SseEmitter(0L);
        try {
        sseEmitter.send("/// 服务端链接成功");
        } catch (IOException e) {
            log.error("用户[{}]推送链接信息异常:{}", userId, e.getMessage());
            sseEmitterMap.remove(userId);
        }

        // 注册回调
        sseEmitter.onCompletion(() -> sseEmitterMap.remove(userId));
        sseEmitter.onError(throwable -> {
            log.info("连接异常:{}", userId);
            sseEmitterMap.remove(userId);
        });
        sseEmitter.onTimeout(() -> sseEmitterMap.remove(userId));
        sseEmitterMap.put(userId, sseEmitter);
        return sseEmitter;
    }

    public void sendMessage(String userId) {
        if (sseEmitterMap.containsKey(userId)) {
            try {
                sseEmitterMap.get(userId).send("Hello SSE");
            } catch (IOException e) {
                log.error("用户[{}]推送异常:{}", userId, e.getMessage());
                sseEmitterMap.remove(userId);
            }
        }
    }

}

核心方法就是这么简单,我们就可以完成服务端向客户端发送实时消息,接下来就是添加测试controller(省略。。。),进行测试看效果。

  • 测试效果

SSE VS WebSocket

SSE WebSocket
通信 单向通信 双向通信
协议 HTTP协议 WebSocket
数据格式 文本格式 文本格式/二进制数据
断线重连 支持 需要自己实现

总结

SSE 的本质其实就是一个HTTP的长连接 ,只不过它给客户端发送的不是一次性的数据包,而是一个stream流,格式为text/event-stream。所以客户端不会关闭连接,会一直等着服务器发过来的新的数据流。

最后,还是那句话,每一种方案都有自己的优缺点,而我们能做的就是在不同场景下,选用合适的方案,再通过一些机制来弥补方案的缺点。

相关推荐
天丁o34 分钟前
Spring Boot + MyBatis Plus 考勤日报统计报表:打卡记录聚合、异常分类和明细下钻 Demo
spring boot·mybatis plus·企业数字化·考勤系统·报表统计
Devin~Y1 小时前
从本地生活电商到 AI RAG:互联网大厂 Java 面试场景完整实战
java·spring boot·redis·elasticsearch·spring cloud·kafka·rag
米码收割机1 小时前
SA508-3钢回火焊道焊接温度场数值模拟(模拟图+论文)
spring boot·express·宠物
JackSparrow4141 小时前
前端安全之JS混淆+请求加密+请求签名以提升爬虫难度
前端·javascript·后端·爬虫·python·安全
geovindu1 小时前
go:loghelper
开发语言·后端·golang
小满zs2 小时前
Go语言第四章(类型转换)
后端·go
米码收割机3 小时前
【项目】spring boot+vue3 宠物领养系统(源码+文档)【独一无二】
java·spring boot·宠物
人间凡尔赛4 小时前
告别冷启动!WebAssembly + Spin 实战:Serverless 延迟从 1 秒降到 1 毫秒
后端·云原生·serverless·webassembly·spin
陈随易10 小时前
bm2,MoonBit实现的pm2替代品
前端·后端·程序员
都叫我大帅哥12 小时前
Spring Data JPA 查询之道:方法命名与示例查询完全指南
java·后端·spring