推送消息到手机?从推送原理到自建MQTT链路实践

互联网推送服务原理:长连接+心跳机制(MQTT协议) 在将这个之前我们先来了解一下 mqtt,MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。 MQTT协议是为大量计算能力有限,且工作在低带宽、不可 阅读详情

你第一次接触“推送消息到手机”这个需求时,很可能觉得很简单:后端调用一个接口,手机端收到通知,完事。但等真把App装到测试机上,你很快会遇到一系列让人困惑的现象——App刚退到后台就收不到消息了,换了一台安卓手机行为完全不一样,iOS那边永远比你预想得多一道签名流程。更麻烦的是,很多后台推送服务显示“发送成功”,用户手机上却什么都没有。

这篇文章想解释清楚一个核心判断:消息推送的难点不是“把消息发出去”,而是“如何在设备不在线、进程被杀、用户关掉通知权限的情况下,仍然把消息可靠地送到用户眼前”。如果你只是写个接口让App每秒轮询一次,开发环境看着没问题,线上大概率会崩。真正适合长期使用的推送体系,需要先做好技术选型,再决定是自己搭一套通道,还是接入厂商推送SDK。

文章会先讲清楚消息推送的基本原理,然后给出一份选型清单,接着用最小成本搭建一条“服务端 → EMQX → Android手机”的完整推送链路。你可以通过一条命令触发订单状态推送,在手机端实时收到结果。最后,我会把生产环境里那些真正容易踩坑的地方和排查思路列出来。这是一篇偏向实践的文章,适合后端开发、App开发,以及准备做IoT或内部工具通知的开发团队阅读。

1. 这篇文章真正要解决的问题

很多团队接到“推送消息到手机”的需求时,第一反应是扩展现有的HTTP接口:App每隔几秒去服务端查一次状态。这种方案有个形象的称呼叫“轮询”。轮询在最简单的场景下确实能工作,但它有几个隐藏成本。

首先,轮询造成大量无效请求。用户没有新消息时,App仍然要每隔几秒发一次请求,这浪费用户流量,也浪费服务端连接资源。想象一下,如果有1万个在线用户,每个用户每5秒请求一次,服务端每秒要扛2000次请求,而其中绝大多数请求根本拿不到新数据。其次,轮询的实时性永远受“轮询间隔”限制。间隔设短了浪费资源,设长了用户会觉得消息来得太慢。更麻烦的是,当App进程被系统回收后,轮询代码根本没机会执行,消息自然就收不到。

推送和普通请求的核心差别在于:普通请求是“客户端主动去取”,推送是“服务端主动把消息塞给客户端”。要做到后者,客户端必须和推送服务保持一个实时在线的长连接。长连接由谁来维护、进程被杀后还能不能继续工作,这决定了不同推送方案的能力边界。

看完本文你应该能回答下面几个问题:

  • 为什么不能靠HTTP轮询顶替推送?
  • APNs、厂商通道、聚合Push、自建MQTT分别解决什么问题?
  • 从零搭一条自建推送链路需要哪些组件?
  • 为什么服务端显示发送成功,手机却收不到通知?
  • 生产环境下,自建推送有哪些绕不开的工程细节?

2. 消息推送核心原理:Push与Pull的本质差异

2.1 Push与Pull的区别

Push和Pull描述的是消息流动的方向。Pull是客户端主动询问服务端“有没有新数据”,服务端被请求后才返回结果。Push是服务端一旦产生新消息,就主动通过长连接把数据推给客户端。

日常开发里最常见的Pull就是轮询。它的优点是实现简单,服务端只要提供普通HTTP接口即可,不需要维护额外的长连接服务。缺点是实时性受制于轮询周期,而且服务端无法主动感知客户端是否还活着。Push则反过来,服务端维护与客户端的连接状态,消息一来就往下发。它的实时性更好,省去大量无效请求,但复杂度明显更高,需要额外设计消息通道、连接保活、离线消息等机制。

用生活中的例子来理解:Pull就像你去快递柜取件,快递到了先放在柜子里,你有空就去刷一下柜子看看有没有新包裹;Push则像快递员直接打电话告诉你“包裹到了”。前者需要你反复检查,后者不需要你主动关心,前提是快递员知道你的手机号且你的手机开机。

2.2 系统级长连接与App自建长连接

真正影响推送到达率的关键,是长连接由谁来维护。

系统级长连接是指操作系统自己维护的一条连接。比如iOS的APNs、安卓手机厂商的推送服务,它们作为系统组件常驻,App即使没有被启动,系统收到新消息后也能通过通知栏把内容展示给用户。这个过程对App来说是透明的,你的App进程是否活着通常不影响消息的最终展示。这是市面上主流App能够做到“杀不掉”通知的核心原因。

App自建长连接则是指App自己启动一个网络连接,在后台维持与某个推送服务器的通信。比如接入一个自己的WebSocket服务,或者通过MQTT保持一条TCP长连接。这种连接一旦App进程被杀,连接就断了,消息也就收不到了。除非你的App能够成为系统白名单应用,或者用户手动允许App后台自启动,否则自建通道很难保证高到达率。

这也是判断一个Push方案能不能用于面向大众用户的C端产品时,最核心的一个分水岭。系统级通道做不好,App保住不了,那消息到达率就一定会打折扣。

2.3 MQTT协议为什么适合推送场景

如果把“推送”抽象成“让一个消息从服务端到达指定设备”,那么MQTT是一个非常适合的协议候选。MQTT全称是Message Queuing Telemetry Transport,最初是为低带宽、不可靠网络环境设计的轻量消息协议。它的核心模型是发布/订阅:发送者把消息发布到某个主题,订阅了这个主题的客户端会收到消息。

MQTT不太像传统消息队列,倒更像一个“群聊”:谁在群里订阅了这个主题,谁就能收到消息。服务端不用显式维护“每个设备该发什么”的地址表,设备连上来之后自己订阅即可。一对多、多对多都方便。MQTT的报文头部开销非常小,适合移动网络;它还支持QoS 0、1、2三种投递级别,服务端可以按业务要求选择是否需要确认消息送达。

需要注意的是,不要把MQTT和Kafka混为一谈。Kafka面向大数据场景下的流式吞吐,侧重消息堆积与顺序处理;MQTT面向物联网和移动弱网,侧重设备连接数、低带宽和弱网稳定性。如果只是给几千或几万台设备推送简单状态,MQTT是非常轻量的选择;如果你要做海量日志收集或事件流分析,那应该考虑Kafka这类消息中间件。

2.4 名词澄清:推送消息、通知栏消息、透传消息

不少新手会混淆“推送消息”和“通知栏消息”。在多数推送SDK的语境里,通知栏消息是指系统收到消息后直接展示成一条系统通知;透传消息则是指服务端把一段自定义数据发给App,App决定如何处理,是否弹通知、弹什么样的通知都由App自己控制。

通知栏消息的好处是不需要App进程在前台,系统会展示;坏处是展示样式和点击跳转让渡给了系统或SDK的默认行为。透传消息的好处是灵活,App拿到数据后可以更新页面、播放声音、执行静默任务等;坏处是如果App进程不在,消息大概率收不到,至少不能保证及时处理。

做技术选型时,一定要先确认:你要的是“让用户看到一条通知”,还是“让App后台更新数据”。很多需求表面上写着“推送消息到手机”,实际拆解后做的却是另一件事。比如App内小红点数量更新,完全可以在前台通过WebSocket更新,不需要走厂商推送通道;但用户关闭App后收到营销活动通知,那才需要系统级通道。

3. 技术选型:系统推送、厂商聚合与自建推送

3.1 主流推送方案对比

方案 维护方 核心优势 主要限制 适用场景
APNs 苹果 iOS系统统一推送,进程被杀也能收到 只覆盖苹果设备,且需要配置证书和密钥 iOS App
FCM Google 安卓官方方案,功能完整 依赖Google Play服务,国内安卓设备接入范围有限 海外安卓应用
厂商通道 小米、华为、OPPO、vivo等 系统级推送,各厂商后台保活能力强 需逐一接入各家SDK,各家能力不一致 国内安卓C端App
聚合推送 极光、个推、友盟等 一套SDK封装多厂商通道,开发成本低 受第三方SDK稳定性影响,部分能力需付费 不想逐个适配厂商的团队
IM客户端消息推送的几种方式及特点 提起消息推送一般人们会经常提起的有以下几种:1. 轮询顾名思义,客户端定期去向服务端询问是否有新的消息,简单点说就是服务端不关心客户端的地址是什么,客户端来询问,直接告诉它就行。这种方案最简单,但是却不适用于即时通讯产品,因为即时通讯软件的消息传递机制与一般的消息推送的区别就在即时这点,如果采用轮询的方式,客户端每几秒就连一次服务器,对于手机电量与流量的消耗是很大的。2. XMPPXMPP是一种基... 阅读详情

相关推荐

从原理到实战:彻底掌握 MQTT 高效使用场景

MQTT协议是专为物联网设计的轻量级通信协议,采用发布/订阅模式实现设备间高效稳定通信。文章详细解析了MQTT的核心设计哲学、适用场景(如智能家居、工业监测等)、三大QoS等级(最多/至少/恰好一次)的实现机制,以及其精简的数据包结构(固定报头仅2字节)。通过图解和表格展示了MQTT在低带宽、高延迟网络中的优势,包括主题路由、遗言机制、持久会话等特性,并给出不同场景下的QoS选型建议。全文从协议原理到实战应用,系统阐述了MQTT如何解决物联网设备在资源受限环境下的通信难题。

人心有反复,好在山水有重逢。 2759

“妹妹出没”系统实战:ESP32人体感应与MQTT消息推送

物联网(IoT)的普及让智能家居方案变得轻量而高效。消息队列遥测传输(MQTT)协议因低带宽、低功耗特性,成为设备与服务器通信的常用桥梁。结合人体红外(PIR)传感器与微控制器(如ESP32),开发者可构建隐私友好的存在检测系统。这类系统不仅适用于家庭出入提醒、老人看护等场景,还能通过事件记录与实时推送提升生活便利性。本文基于一个名为“妹妹出没”的实践项目,演示如何用ESP32读取PIR状态,经MQTT发布到本地Broker,再由Python服务订阅并存入SQLite,最后通过Flask展示历史记录并推送通

weixin_30175731的博客 229

Android MQTT消息推送实践:从Paho接入到连接保活与通知栏适配

在物联网与移动应用开发中,实时消息推送是连接设备与用户的关键环节。MQTT作为一种轻量级发布/订阅消息传输协议,凭借低带宽消耗、高可靠性及对不稳定网络的良好适配,成为IoT场景的首选。其基于主题路由、QoS分级和持久化会话等机制,能够有效解决传统HTTP轮询带来的资源浪费和实时性不足问题。在Android端落地时,开发者常面临连接保活、断线重连、通知栏适配等实践难题。本文以Eclipse Paho客户端为例,系统梳理了Android集成MQTT的完整链路,涵盖依赖配置、消息订阅与回调、通知通道适配、后台保活

weixin_42524703的博客 137

关键词‖旋变传感器

旋转变压器(以下简称旋变)安装在永磁同步驱动电机的非传动端,其作用是检测转子的位置和速度。目前,通常采采用结构简单、坚固耐用、环境适应性好的磁阻式旋变作为位置传感器。

m0_72345077的博客 2151

S32K系列之PDB框图详解及PDB触发ADC

可编程延迟模块PDB,PDB可提供从内部或外部触发或可编程间隔信号到ADC硬件触发输入的可控制延迟。 PDB可以选择提供脉冲输出,用作CMP块中的采样窗口。 S32K系列的PDB资源如下表: PDB功能框图 在下图中,以下字母表示的意义: N:PDB通道的总数 n:PDB通道号,范围从0到N-1 M:每个PDB通道的总可用预触发 m:预触发编号,范围从0到M-1 Y:脉冲输出的总数 y:脉冲数...

zz56z56的博客 1万+

DTS 数据迁移

支持关系型数据库(MySQL, Oracle, SQL Server等)、NoSQL数据库、大数据系统等。DTS数据迁移是现代化数据架构调整和云迁移过程中的重要工具,能够大大降低数据迁移的复杂度和风险。DTS (Data Transmission Service) 是一种数据迁移和同步服务,:先迁移历史数据(全量),再实时同步新增变化(增量):不同数据库类型间迁移,如Oracle到MySQL。:将单库数据迁移到分库分表架构。:将业务数据迁移到分析型数据库。:将本地数据库迁移到云数据库。

qq_41081716的博客 749

ANSYS 12.1避坑全记录:当Win7+VMware14遇到FLEXlm报错时的自救指南

本文详细介绍了在Windows 7和VMware14环境下安装和运行ANSYS 12.1时遇到的FLEXlm报错问题及其解决方案。通过虚拟机技术隔离时间同步问题,提供从环境配置到许可证管理的完整指南,帮助用户稳定运行这一老旧版本的工程仿真软件。

tt34567的博客 644

告别安装烦恼!Orange3 3.38.0 Windows绿色版下载即用,附保姆级汉化与组件配置指南

本文详细介绍了Orange3 3.38.0 Windows绿色版的下载与使用,包括中文汉化、组件配置及高效管理技巧。这款无需安装的数据科学工具特别适合快速验证想法的研究人员和移动办公用户,支持多种数据源和可视化工具,大幅提升工作效率。

weixin_30897233的博客 602

基于AutoDL复现A-LOAM

Ceres solver 是谷歌开发的一款用于非线性优化的库,在谷歌的开源激光雷达slam项目cartographer中被大量使用。在autodl上面租服务器,地区我租的重庆A区的,GPU我选择的是RTX4090,基础镜像选择的是Miniconda / conda3 / 3.8(ubuntu20.04)/11.6。在AutoDL中我使用的方式是先将该数据集先下载到自己的电脑上,然后再上传到虚拟机中。用MobaXterm解决该问题!搜到的一个解决方式:该问题属于ceres版本问题,将A-LOAM下的。

m0_61281610的博客 1942

五、MT8168 音频驱动之SPEAKER

本章主要讲解MT8168平台的内部SPEAKER驱动配置。分为HP接法和LINE OUT接法。2.1.3 audio_custom_exp.h设置。2.1.4 mixer_paths.xml设置。2.2.3 mixer_paths.xml设置。2.1.2 ProjectConfig 设置。2.2.2 ProjectConfig 设置。2.2.1 deconfig设置。2.1.1 DTS设置。......

Joon2020的博客 1664

Ascend开发包Acllite安装

设置环境变量,配置程序编译依赖的头文件,库文件路径。“$HOME/Ascend”请替换“Ascend-cann-toolkit”包的实际安装路径。将YOLOV7原始模型转换为适配昇腾310处理器的离线模型(*.om文件),放在model路径下。运行完成后,会在样例工程的out目录下生成推理后的图片,显示对比结果如下所示。可以使用以下两种方式下载,请选择其中一种进行源码准备。请从以下链接获取该样例的输入图片,放在data目录下。执行以下命令,执行编译脚本,开始样例编译。执行运行脚本,开始样例运行。

如果想成为中心,那么就到中心去吧。 318

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

上一篇: Java生产级RAG系统:边缘部署、内存优化与知识库工程化
下一篇: 从问答到控制:AI模型在循环工程中作为运行时控制器的评测之道
cuixie2370
博客等级 码龄10年 17粉丝 842原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值