V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
awesomePower
V2EX  ›  程序员

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

  •  
  •   awesomePower · 234 天前 · 2971 次点击
    这是一个创建于 234 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    20 条回复    2024-03-29 08:31:12 +08:00
    vcn8yjOogEL
        1
    vcn8yjOogEL  
       234 天前   ❤️ 6
    设备向服务端发起一个连接, 并定时发送心跳包维持这个连接
    通知到达后服务器通过这个连接向设备推送, 如果设备不在线就放进缓冲区等待设备上线

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

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

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

    ---

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

    微信在国内会自己挂一个推送服务并将 FCM 作为备用推送渠道, 国外则会直接用 FCM
    vcn8yjOogEL
        2
    vcn8yjOogEL  
       234 天前
    心跳包的发送频率应当根据网络环境自动调整
    vcn8yjOogEL
        3
    vcn8yjOogEL  
       234 天前
    主要压力在服务器后端, 能用厂商提供的设施就不要自己做
    coderxy
        4
    coderxy  
       234 天前   ❤️ 1
    本质上就是一个千万同时在线的 im 服务器而已,只不过这个场景,绝大多数 client 在大部分时间都是只保持一个心跳状态, 真的有推送了才会有信息交互。基本上用的应该都还是 tcp
    bronyakaka
        5
    bronyakaka  
       233 天前   ❤️ 2
    对于 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
        6
    zed1018  
       233 天前
    websocket MQTT
    gamexg
        7
    gamexg  
       233 天前   ❤️ 1
    如前面说的,
    就是设备向服务器建立一个 tcp 连接,然后这个连接基本可以看作永久不关闭, 设备或服务器定时通过这个连接发送 包,并检查是否收到回应.
    如果设备发现这个连接存在问题,则重新建立一个连接替换掉原来的连接.

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

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

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

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

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

    dperf 的 TCP 协议栈单机可以做到几十亿并发。https://github.com/baidu/dperf
    awesomePower
        20
    awesomePower  
    OP
       232 天前
    @me1onsoda
    @ben666
    谢谢分享
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2718 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 12:29 · PVG 20:29 · LAX 04:29 · JFK 07:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.