You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过自托管SpringBoot无外部服务向前端发送推送通知

完全自建、无第三方依赖的SpringBoot移动端推送实现方案

核心逻辑

要绕开Firebase这类第三方推送服务,本质就是让移动端和你预留的专用推送节点之间直连长连接,所有消息流转全走自己的服务器集群,不需要经过任何外部服务商的系统,完全可控。

具体落地步骤

1. 专用推送节点配置(你规划的单独Ubuntu节点)

  • 不要把推送逻辑耦合到现有业务SpringBoot应用里,单独在这台节点部署一个轻量的推送微服务,和其余两台业务节点走内网通信即可。负载均衡规则里把这台节点从普通业务请求的轮询池里摘出来,专门预留带宽处理长连接。
  • 长连接优先选WebSocket协议,SpringBoot原生就支持,引入spring-boot-starter-websocket依赖就能快速搭建服务端,对Android和后续Flutter的兼容性都很好,比裸写TCP Socket省大量适配工作。
  • 服务端维护一份连接映射表:移动端首次建立连接时,携带自身绑定的用户ID、设备唯一标识,服务端将「用户ID-设备标识-活跃连接实例」的映射存在本地内存,同时同步到你现有SQL数据库做持久化,设备断连时自动清理无效映射。
  • 做离线消息兜底:设备处于断连状态时,待推送的消息先写入SQL库的离线消息表,等设备下次重连成功,先拉取所有未读离线消息,再启动长连接保活流程,避免丢消息。
  • 先调系统参数:Ubuntu默认单进程文件句柄上限是1024,先修改/etc/security/limits.conf里的nofile参数到65535以上,不然长连接数过千就会报错,普通家用PC配置调完参数撑几万条长连接完全够用。

2. Android测试阶段实现

  • 不需要对接任何厂商或Google的系统级推送通道,App启动后启动一个前台服务,维持和推送节点的WebSocket长连接,初始测试阶段把心跳间隔设为30秒,后续根据你家宽带的NAT超时规则调整即可,避免空闲连接被运营商路由强制断开。
  • 长连接收到消息体后,直接调用Android原生NotificationCompat接口弹出本地通知,全程不需要依赖Google服务框架。测试阶段记得给App开电池优化白名单,避免系统杀后台导致连接断开。
  • 重连逻辑做指数退避:网络异常断开后,第一次等1秒重连,失败就依次等2秒、4秒、8秒,最长重连间隔设为5分钟,不要无限制高频重连把节点打挂。

3. 后续Flutter迁移适配

  • 推送节点的代码完全不需要改动,Flutter端直接用web_socket_channel包对接同一个WebSocket接口即可,本地通知调用flutter_local_notifications插件实现。前后端提前统一消息体JSON格式,固定包含消息ID、标题、内容、跳转路径、发送时间字段,迁移时后端零改动。

4. 集群适配注意事项

  • 给推送节点分配固定的内网/公网访问地址,不要让WebSocket连接走普通业务的负载均衡轮询,不然每次重连落到不同节点会导致消息投递失败。
  • 其余业务节点需要发推送时,直接走内网调用推送节点的发信接口即可,接口只允许内网访问,加简单的token鉴权,避免公网暴露被恶意盗刷。

可选优化方向

  • 如果后续觉得WebSocket保活流量消耗高,可以把长连接换成MQTT协议,在推送节点部署开源的MQTT broker即可,比原生WebSocket更适合推送场景,Android和Flutter端的MQTT客户端库都非常成熟,同样不需要依赖任何外部服务。
  • 消息传输可以加一层RSA+AES混合加密,避免公网传输时被窃听篡改,密钥在App首次启动时通过业务接口协商即可。

内容的提问来源于stack exchange,提问作者Priyesh Jakhmola

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 01:45:42