Stream-Nexus:我的轻量级推送中间件(sse、websocket)终于定下来了

关注我的公众号:【编程朝花夕拾】,可获取首发内容。

01 引言

前一段时间一直做推送业务,于是整理了一个项目:Stream-Nexus。但是想要表达的东西总是达不到自己想要的效果,于是这两天一直折腾。之前在GitHub上托管了一版,总觉的差点意思,现在终于可以确定下来,不会大改了。后续想要有趣的功能会持续集成。本节就重新介绍一下这个项目。

02 简介

Stream-Nexus中文叫流枢,一个让消息以流的形式持续流动、由中心枢纽统一调度和路由的推送系统。只用来接收订阅和推送消息给客户端。至于从那里推送,可以通过客户端接入的方式任意推送。

项目结构:

text 复制代码
stream-nexus
├── pom.xml                # 父 POM
├── .dockerignore          # 构建上下文瘦身
├── docs/                  # 使用说明文档
├── nexus-client/          # 独立的客户端
├── nexus-common/          # 跨模块契约(消息体、枚举、常量、入参出参)
├── nexus-sse/             # SSE 推送服务实现(端口 8088)
└── nexus-websocket/       # WebSocket 推送服务实现【待优化】
  • nexus-common:跨模块公用参数
  • nexus-sse:SSE推送服务
  • nexus-websocket:Websocket推送服务
  • nexus-client:独立的客户端,引入业务项目快速推送消息

GitHub地址:github.com/simonking-w...

03 SSE推送服务

3.1 简介

nexus-sse基于原生EventSource,以SpringBoot4.x为基座实现了极简的推送服务。业务系统通过 HTTP 灌消息,浏览器用 EventSource 收消息。

  • 零中间件依赖:连接表与消息 ID 全在内存,不需要 Redis / MQ
  • 单机 java -jar 即可跑,接入成本极低
  • 适合中小规模实时推送场景

⚠️ 受浏览器同源策略影响,同源仅支持 6 个 SSE 长连接,后续计划集成 WebSocket 模块来突破这个限制。

3.2 特点

  • 客户端的的订阅、发送消息增加了鉴权,并按应用限制模块白名单
  • 心跳保活,服务端每 15s 下发 PING,客户端回 PONG。防止 LB / NAT 空闲断链
  • 管理页面需要登录才能进入
  • /admin 连接台账 + 应用管理,/console 推送测试页,也可以测试其他EventSource连接。
  • 推送页面增加动态监听event事件标签,用来测试外部自定事件
  • 页面主题增加主题切换:亮色背景/暗色背景
  • 部署支持Docker部署

3.3 效果实例

登录页

管理界面

推送页面

亮色主题

04 Websocket服务

4.1 简介

nexus-websocket 与 SSE 通道定位互补:SSE 是「HTTP 生态、单向、浏览器原生重连」,WebSocket 是「全双工、可上行、适合高频交互」。两者协议与端口完全独立,可同时部署。

nexus-websocket内置了TCP和websocket服务端。websocket用来和前端建立建立,而TCP作为转达层,通过业务系统的TCP客户单发送消息,然后有TCP服务端直接通过调用WebSocket服务推送给前端。

这个实践是来源于之前发布的一篇文章实现的:<<神了,WebSocket竟然可以这么设计!>>

WebSocket 服务独立部署,业务系统不写任何 Netty / WebSocket 服务端代码,而是通过「REST 接口(或 TCP 长连接)」把消息交给它,由它转发给终端。

text 复制代码
浏览器 / H5 / App
          │  ws://host:9090/ws?modules=test
          ▼
   nexus-websocket(独立部署,一个进程三组端口)
     ├── 9090  Netty WebSocket ------ 终端长连接
     ├── 9091  Netty TCP       ------ 业务系统长连接(连上即可推,只对内网开放)
     └── 8089  HTTP            ------ REST 推送入口 / 管理界面 / 测试页 / 运维接口
          ▲
          │  HTTP POST /ws/push(短连接)或 TCP 长连接(9091)
   业务系统 ← nexus-client(或直接 HTTP 调用)

4.2 特点

  • 除了TCP推送以外,还支持Rest调用,Rest调用增加鉴权
  • 客户单的建立支持参数,用来区分不同模块
  • 四条判据(回调 / 心跳超时 / 软重置 / 写入失败)统一回收,避免半开连接堆积

4.3 示例

nexus-websocket目前还没有细化,只是作出了大致框架,页面的展示同nexus-sse。

05 SDK客户端

nexus-client是nexus-sse / nexus-websocket 推送服务的客户端 SDK ,一次 HTTP POST 或一条 TCP 长连接就能把消息推到浏览器, 完全不需要编写任何 SSE / Netty / WebSocket 服务端代码。

传统做法里,每个业务系统都要复制一份长连接服务端代码(SseEmitter / ServerBootstrap、握手、ChannelGroup......), N 个系统就是 N 份重复实现。现在不需要了,只要引入依赖就可以无门槛使用。

为了能够适配低版本的JDK,nexus-client按照Java 8打包。

5.1 使用

xml 复制代码
<dependency>
    <groupId>com.simonking.nexus</groupId>
    <artifactId>nexus-client</artifactId>
    <version>1.0.0</version>
</dependency>

这个目前还没有发布到中央仓库,后续可以考虑发布到中央仓库,方便使用。

5.2 使用示例

java 复制代码
// 1. 构造:两个服务各一组「地址 + 鉴权」,用哪个填哪个(只推 SSE 就可以不写 ws*)
NexusRestClient client = NexusRestClient.builder()
        .sseBaseUrl("http://10.0.0.8:8088").sseAppId("order-service").sseApiKey("sse-key")
        .wsBaseUrl("http://10.0.0.8:8089").wsAppId("order-service").wsApiKey("ws-key")
        .build();

// 2. 推:按终端类型挑方法,一次 HTTP POST,同步拿回执
Map<String, Object> data = new HashMap<>();
data.put("orderId", 1001);
data.put("amount", 99.9);
PushRequest request = PushRequest.builder().bizModule("order").action("CREATE").data(data).build();

PushResult sseResult = client.ssePush(request);   // 推给 SSE 终端(POST /sse/push)
PushResult wsResult = client.wsPush(request);     // 推给 WebSocket 终端(POST /ws/push)
System.out.println("命中 " + wsResult.getTotal() + " 条,成功 " + wsResult.getSuccess() + " 条");

// 3. 应用退出时释放(停调度线程、清连接池)
client.close();
相关推荐
打工仔折腾 AI1 小时前
网易UU远程实测:手机控电脑做Python开发和Agent调试的真实体验
人工智能·后端·python·智能手机·性能优化·电脑·ai agent 实战
边境悍匪1 小时前
蜗牛学苑 Java 智能体学习 Day49|贯穿项目 5 订单下单业务 思维导图复盘
java·开发语言·spring boot·学习·阿里云
鬼手点金2 小时前
Claude Code示范案例-修复 Bug 工作流
java·服务器·前端·javascript·bug·openclaw
一条破秋裤2 小时前
Linux 进程通信介绍:内存隔离与 IPC 分类
java·linux·服务器
YYYing.2 小时前
【设计模式系列 (四) 】建造者模式
c++·后端·设计模式·建造者模式·c/c++
机核研创社2 小时前
polo 长袖短裤套装自动化产线:八台机器排队接力
android·java·自动化
Roadinforest2 小时前
Spring Boot 4 六步入门实录:从 Hello World 到一个能交付的 Todo API
java·开发语言·spring boot·spring
半仙白桑2 小时前
内核篇第十三讲:system-V消息队列
java·linux·网络