一次通话向所有订阅者发送网络推送通知

Posted

技术标签:

【中文标题】一次通话向所有订阅者发送网络推送通知【英文标题】:Send web push notification to all subscribers in one call 【发布时间】:2019-10-18 07:49:02 【问题描述】:

我正在我的网站中使用服务人员实现网络推送通知。我有一个工作网站,每隔一小时就会发布新工作。我想在发布新工作时通知订阅者。 我已经完成了让用户订阅和编写节点服务器以及通过生成 VAPID 密钥来发送推送通知的实现。

我有一个问题,我觉得当我需要向所有订阅者发送推送通知时,我是否需要为每个用户发送新呼叫,或者有某种机制可以在一次呼叫中将其发送给所有订阅者。

例如,如果我有 100,000 个,那么我是否需要拨打 100,000 个电话,或者有其他方法可以一次性发送 1 个电话并通知所有 100,000 个订阅者有关新工作更新的信息?

我绝对觉得如果我一次发送数千个调用,我会被相关的浏览器服务扼杀。

有没有办法通过一个电话来做到这一点?

这是我当前从快速服务器向所有订阅者发送通知的代码路线。

const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Subscription = mongoose.model('subscribers');
const q = require('q');
const webPush = require('web-push');
const keys = require('./../config/keys');
router.post('/', (req, res) => 
    const payload = 
        title: req.body.title,
        message: req.body.message,
        url: req.body.url,
        ttl: req.body.ttl,
        icon: req.body.icon,
        image: req.body.image,
        badge: req.body.badge,
        tag: req.body.tag
    ;

Subscription.find(, (err, subscriptions) => 
    if (err) 
        console.error(`Error occurred while getting subscriptions`);
        res.status(500).json(
            error: 'Technical error occurred'
        );
     else 
        let parallelSubscriptionCalls = subscriptions.map((subscription) => 
            return new Promise((resolve, reject) => 
                const pushSubscription = 
                    endpoint: subscription.endpoint,
                    keys: 
                        p256dh: subscription.keys.p256dh,
                        auth: subscription.keys.auth
                    
                ;

                const pushPayload = JSON.stringify(payload);
                const pushOptions = 
                    vapidDetails: 
                        subject: 'http://example.com',
                        privateKey: keys.privateKey,
                        publicKey: keys.publicKey
                    ,
                    TTL: payload.ttl,
                    headers: 
                ;
                webPush.sendNotification(
                    pushSubscription,
                    pushPayload,
                    pushOptions
                ).then((value) => 
                    resolve(
                        status: true,
                        endpoint: subscription.endpoint,
                        data: value
                    );
                ).catch((err) => 
                    reject(
                        status: false,
                        endpoint: subscription.endpoint,
                        data: err
                    );
                );
            );
        );
        q.allSettled(parallelSubscriptionCalls).then((pushResults) => 
            console.info(pushResults);
        );
        res.json(
            data: 'Push triggered'
        );
    
);

);

router.get('/', (req, res) => 
    res.json(
        data: 'Invalid Request Bad'
    );
);
module.exports = router;

【问题讨论】:

【参考方案1】:

目前,网络推送标准不允许向多个收件人发送相同的通知:如果您直接处理浏览器推送服务,则需要为每个收件人拨打不同的电话。

我已经在 2016 年的 Github 官方仓库中问过这个问题: https://github.com/w3c/push-api/issues/208

如果您想卸载您的应用程序,您可以使用推送服务来代表您完成这项工作:然后您对推送服务进行一次 API 调用,它会向浏览器推送服务进行数千次调用。

对于目前的限制,我没有发现任何问题,即使每小时有几百万条通知。

【讨论】:

感谢@collionmacro 的留言。现在我明白了为什么它不能通过单个请求来完成,因为它是协议的一部分。我现在要么使用单独的机器发送通知,因为我有大量的用户将订阅。【参考方案2】:

如果您只想进行一次 API 调用,可以使用 Firebase。您可以只为您的用户订阅一个“主题”,然后对 FCM 端点进行一次 API 调用,在请求正文中指定该主题,然后让 Google 处理所有工作以向您的订阅者发送推送通知。您也可以在您的 firabase 项目中使用您当前的 VAPID 密钥。

【讨论】:

已经这样做了。现在使用 firebase 向主题的所有成员发送通知。无论如何感谢您的回复。

以上是关于一次通话向所有订阅者发送网络推送通知的主要内容,如果未能解决你的问题,请参考以下文章

Azure 向多个设备/广播发送推送通知

一次向多个设备推送通知

我们可以使用 Firebase 向独立用户发送自定义推送通知吗?

iOS 推送通知 - 向所有人发送消息

iOS:从 AWS SNS 向 APNS 发送推送通知

使用 AWS SNS 向特定 APNS 令牌发送推送通知