求教,推送的本质是什么?服务器如何向几百万台手机设备推送的信息的

226 天前
 awesomePower

如题。是设备不断向服务器发送 tcp 或者 udp 请求吗?还是服务器记录了设备的网络地址,反向向设备请求。

有了解类似技术细节的大佬告知下吗

2961 次点击
所在节点    程序员
20 条回复
vcn8yjOogEL
226 天前
设备向服务端发起一个连接, 并定时发送心跳包维持这个连接
通知到达后服务器通过这个连接向设备推送, 如果设备不在线就放进缓冲区等待设备上线

一般操作系统会提供一个统一的服务处理所有通知, 例如 Android 的谷歌 FCM 和 iOS 的苹果 APNS

FCM 在国内可以直连, 但没有优化线路所以效果一般, 没有其他谷歌服务使用也麻烦, 所以国产都做了自己的推送服务, 但也因此出现了碎片化, App 需要给不同厂商单独接入

APNS 要求 App 把推送信息交给苹果, 苹果直接把通知推到手机, FCM 则支持让推送唤醒 App, App 去获取实际内容并生成通知; 前者更省电, 但功能有限, 例如 Signal 这种端到端加密聊天因为服务端无法解密而无法通过 APNS 推送消息内容

---

客户端轮询也可以, 但想消除延迟就需要快速唤醒所以很耗电, 一般不建议使用

微信在国内会自己挂一个推送服务并将 FCM 作为备用推送渠道, 国外则会直接用 FCM
vcn8yjOogEL
226 天前
心跳包的发送频率应当根据网络环境自动调整
vcn8yjOogEL
226 天前
主要压力在服务器后端, 能用厂商提供的设施就不要自己做
coderxy
226 天前
本质上就是一个千万同时在线的 im 服务器而已,只不过这个场景,绝大多数 client 在大部分时间都是只保持一个心跳状态, 真的有推送了才会有信息交互。基本上用的应该都还是 tcp
bronyakaka
226 天前
对于 iOS 设备:

使用 Apple Push Notification Service (APNs):每个 iOS 应用在注册推送通知后会获得一个唯一的 Device Token 。服务器端将要推送的消息、目标设备的 Device Token 以及其它必要参数封装成推送请求,发送给 Apple 的 APNs 服务器。
APNs 与每台 iPhone 、iPad 等设备维持一个持久连接(长连接)。
当服务器端发送推送消息时,通过与 APNs 的连接将消息转发至对应的设备。
设备收到推送消息后,即使应用不在前台运行,也能显示通知并将消息存储,用户点击通知时可以唤醒对应的应用。
对于 Android 设备:

Google Firebase Cloud Messaging (FCM) 或其他第三方推送服务:类似 iOS ,Android 设备也会通过相应的服务获取一个 Registration ID ,并将其发送给服务器。
服务器通过与 FCM 服务器接口交互,将消息和目标设备的 Registration ID 一起发送给 FCM 。
FCM 利用自身的长连接网络服务将消息分发到各个设备。
设备接收到消息后,根据消息类型显示通知,或者静默处理。
zed1018
226 天前
websocket MQTT
gamexg
225 天前
如前面说的,
就是设备向服务器建立一个 tcp 连接,然后这个连接基本可以看作永久不关闭, 设备或服务器定时通过这个连接发送 包,并检查是否收到回应.
如果设备发现这个连接存在问题,则重新建立一个连接替换掉原来的连接.

如果服务器需要通知设备,则直接通过这个连接向设备发送数据即可.

现在服务器性能是很不错的,应付大量的这种连接没什么问题.
haikea
225 天前
服务器不可以主动请求设备吧?应该都是设备向服务器发送请求。你可以了解一下物联网常用的 MQTT
gochat
225 天前
https://github.com/LockGit/gochat 即时通讯系统,可以了解下
gochat
225 天前
Tabjy
225 天前
@vcn8yjOogEL

> 前者更省电, 但功能有限, 例如 Signal 这种端到端加密聊天因为服务端无法解密而无法通过 APNS 推送消息内容

不是 ios 开发者,但是好像有个 notification service app extension [0] 可以被系统调用主动并处理通知

[0] https://developer.apple.com/documentation/usernotifications/modifying-content-in-newly-delivered-notifications
opengps
225 天前
前几楼说的足够详细了,我简略说几句:
1 ,如果是应用自己的连接,那么需要程序运行,有一个公用的 socket 服务(通常是 tcp ),作为客户端,主动连接服务端,登陆后先发送自己的 id ,所以服务器可以随时下发信息。最典型的应用是所有的实时位置服务类应用,比如打车软件。
2 ,如果应用自己没做连接,则需要借助手机系统自身的推送来实现,手机厂商维护了一个公共的连接,可以转发,因此可以做到 app 没运行都被系统通知,然后通过点击来“叫醒”app
awesomePower
225 天前
awesomePower
225 天前
服务器保持这么多 TCP 连接,会不会压力很大
qinfengge
225 天前
看下极光 push ,国内每家安卓厂商都有自己的推送渠道,可以在不打开 APP 的情况下离线推送,但是需要每家厂商都配一遍,恶心死了。之前说的统一推送联盟直接没下文💩
opengps
225 天前
@awesomePower 只要处理得当,低配单机承载个几万很轻松,甚至十多万也可以(但由于维护困难,比如重启一下程序需要十几分钟才能完成所有连接的重新建立,所以会用多台低端机的方案)
me1onsoda
225 天前
tcp 长连接,server 可以随时写到 channel ,而不是不断的请求
awesomePower
225 天前
@opengps 谢谢解答
ben666
225 天前
对于这种单一的业务,完全可以用 DPDK 实现用户态协议栈,单机支持几百万连接问题不大。
对于很多特定场景的业务,很多大厂都在协议栈上下了很多功夫。

dperf 的 TCP 协议栈单机可以做到几十亿并发。https://github.com/baidu/dperf
awesomePower
224 天前
@me1onsoda
@ben666
谢谢分享

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1027549

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX