推送通知是如何工作的【译】

Posted by Neil Ning on 2023-07-18
翻译

前言

该文章翻译自web.dev的Notifications系列文章,本篇文章原文链接点击这里

在我们讨论推送的API之前,让我们从头到尾完整的回顾一下推送的流程。然后我们再来讨论每一步的细节,你会明白为什么这如此重要。
实现推送需要以下三个关键步骤:

  1. 添加客户端逻辑来将用户订阅到推送服务
  2. 在你的网站服务端调用API触发消息推送给客户端
  3. 当推送的消息到达时,会触发service worker的push事件,并在回调函数中展示消息通知

我们来讨论下以上每个步骤的完整细节

1. 客户端

第一步是用户订阅消息推送,该步骤需要完成两件事,第一件是获得用户授权,第二件是获得浏览器返回的PushSubscription对象,该对象包含了要发送消息给用户的所有信息,某种程度上,你可以将它视作用户设备的ID。以上步骤使用Push API来完成。

但是在用户订阅之前,你需要提前生成一对“应用服务器密钥”(application server keys),这个后面也会讲到。

应用服务器密钥就是我们之前提到的VAPID密钥,在服务器上它是唯一的。它告诉推送服务哪个网站的用户订阅了消息推送,并确保将消息推送给该网站的用户。
用户订阅之后,你会得到PushSubscription对象,你需要将该对象发送给你的服务端,在服务端,你需要将该对象存储在数据库中,因为后续向用户发送消息时需要用到该对象。
subscription.jpg

2. 推送消息

当你打算向用户推送消息时,你需要向推送服务发送API请求,这个API请求包括你要发送的数据、接收消息的客户端信息以及其他有关消息推送的必备字段。该步骤通常在你的服务端完成。
你可能会有一些疑问:

  • 什么是推送服务?
  • API的形式是什么,JSON,XML?
  • API还可以做什么?

什么是推送服务

推送服务可以接收网络请求,然后验证请求,并将消息推送给正确的浏览器。如果浏览器是离线的,消息会被放入队列中,直到浏览器再次上线。
不同的浏览器使用不同的推送服务,开发者无法控制。但是所有的推送服务都必须遵守相同的API调用规则。这意味着你不需要关心谁是推送服务,你只需要确保你的API调用是合法的。
想要知道推送服务的的URL,你可以查看PushSubscription对象的endpoint字段值。下面是一个例子:

1
2
3
4
5
6
7
{
"endpoint": "https://random-push-service.com/some-kind-of-unique-id-1234/v2/",
"keys": {
"p256dh": "BNcRdreALRFXTkOOUHK1EtK2wtaz5Ry4YfYCA_0QTpQtUbVlUls0VJXg7A8u-Ts1XbjhazAkj7I99e8QcYP7DkM=",
"auth": "tBHItJI5svbpez7KI4CCXg=="
}
}

在这个例子中endpoint是[https://random-push-service.com/some-kind-of-unique-id-1234/v2/],推送服务是random-push-service.com,“some-kind-of-unique-id-1234”表明每个用户都有一个唯一的endpoint,随着对推送更加深入的理解,你会注意到endpoint的规律。

对象的中keys字段将在后面解释。

API的形式是什么,JSON,XML?

前面提到,所有推送服务的API调用方式都是相同的,这个API就是Web Push Protocol,它是一份IETF标准,定义了你应该如何向推送服务发送请求。例如API调用要求设定特殊的请求头,数据必须以字节流的形式发送。后面我们会看到工具库可以帮我们完成API调用,以及我们自己应该如何实现它。

API可以做什么

API可以允许你向用户发送消息,或者提供一些特殊的指令。
消息推送的数据必须是经过加密的,这是为了阻止推送服务查看你发送给用户的信息。任意的浏览器厂商都可以决定自己的推送服务,即便这个推送服务没有那么安全。
当你触发一个消息推送,推送服务将会收到API调用,并将消息放入队列,用户的设备处于在线状态时,推送服务会将该消息分发给客户端。API还有一些特殊的指令来指定消息队列的形式。如:

  • 消息的生命周期,他可以指定队列中的消息在多久之后会被删除并不再分发该消息。
  • 消息的紧急程度,发送更高优先级的消息。
  • 消息的主题,他可以将有相同主题的未发送的消息替换为新的消息
    request.jpg

3. 用户设备的推送事件

一旦我们发送消息推送的请求给推送服务,推送服务将会收到你的消息,直到以下事件发生:

  1. 用户设别恢复在线,消息被正确分发给客户端。
  2. 消息过期,推送服务将会移除该消息,并不再分发该消息。

当推送服务将消息分发后,浏览器会解密收到的消息,并在service worker中触发push事件。

我们知道service worker是一段特殊的JS代码,即使在页面关闭时,该代码也会被执行,甚至浏览器关闭时,也可以执行。并且service worker有自己的推送API,它只能在service worker中执行,在网页中是不可用的。
在service worker的push回调函数中,你可以执行任何后台任务,比如发送数据分析请求,离线页面缓存,显示通知等等。
以上就是消息推送的完整流程。

event.jpg