Apple 推送通知:发送大量消息

Posted

技术标签:

【中文标题】Apple 推送通知:发送大量消息【英文标题】:Apple Push Notification: Sending high volumes of messages 【发布时间】:2010-04-06 10:02:10 【问题描述】:

我正在使用 php 连接到 apns 以向多个设备发送一些通知,尽管这个问题更具概念性,因此不必特定于 PHP。

我将同时发送到大约 7000 台设备(并且还在不断增加)。 我的进程每天运行一次并向所有设备广播,因此我不会经常重新打开连接。

目前我可以轻松地一次发送到 2 个设备,并且消息将成功传递。 但是,当我尝试发送到全部 7000 台设备时,消息似乎没有传递。

我的代码的伪逻辑是:

open connection to apple
loop over device-tokens
    write to socket connection per device
end loop
close connection to apple.

我在某处看到我应该只执行一次写入,并构造一个巨大的主体,换句话说,伪代码如下所示:

loop over device tokens
    create payload aggregating all devices
end loop
open connection to apple
write to socket ONCE with whole payload for 7000 devices
close connection

这很难测试,因为我显然不能向我的 7000 名生产用户发送测试消息。 有没有其他人遇到过类似的问题?

谢谢

【问题讨论】:

你有没有得到这个工作?我很快就会编写一个面临同样问题的应用程序——通过 APNS 向成千上万的客户广播。 嗨,迈克。是的,我做到了。我发布此问题时的实施处于相当早期的阶段。问题是我在与生产设备相同的表中有一些沙盒设备。如果您在使用生产证书时发送到沙盒 device_token,Apple 有时会断开连接。因此,简单的解决方案是验证写入连接的字节数是否正确,并且在每次写入事件后连接没有断开。如果它掉线,您必须重新打开连接并从中断处继续。祝你好运! 仅供参考,您可以打开连接并执行任意数量的写入操作。只需确保在每次写入后检查连接状态 是否可以将推送消息广播到多个设备?我可以像你上面提到的那样聚合令牌并向所有设备发送一条消息吗? 呃,是的,这正是我在上面所做的。我在数据库表中收集所有令牌,然后每周一次向所有设备发送相同的消息(甚至可以为每个设备自定义消息。不过,您必须向每个设备的 APNS 发送单独的有效负载。所以如果您有 100 台设备,即 100 次写入套接字 【参考方案1】:

我听说苹果确实关心您与他们的服务器建立的连接数,但我从未听说过任何写入限制。另外,我不确定您会在这里收到什么样的回复,但可能值得一试,看看会发生什么。也许尝试沙盒推送通知服务器,只使用生产设备的设备令牌。这些手机应该不会收到任何发送到沙盒服务器的推送通知,如果沙盒报告“交付成功”,那将是一种无忧的测试方式。

【讨论】:

过期了。但你的回答基本上是正确的。谢谢:) 沙盒需要开发证书,生产需要生产证书。 APNS 文档说,为开发(沙盒环境)构建生成的设备令牌与生产构建完全不同。此外,如果 APNS 生产构建获得由开发构建生成的设备令牌,则会直接使设备令牌无效并断开连接。因此状态不会成功,但连接将被丢弃。对于测试模拟 APNS 服务是一个更好的选择。【参考方案2】:

我明白你想要什么,相反,我确实遇到了同样的问题,对我有用的是逆向工程。 我只是查看了库并检查了验证 deviceToken 的函数。因此,在创建虚拟设备令牌时,我只是确保生成的令牌根据库是有效的。

以下代码将让您生成有效设备令牌,现在由您决定使用此函数生成多少百万个令牌。

   def generateRandomDeviceTokenAndAppendItToJson(tokenLength: Int) 
     val randomlyGeneratedDeviceToken = new StringBuilder()
      randomlyGeneratedDeviceToken.append("          \"")
        (1 to tokenLength) foreach 
         times: Int =>
        if (tokenLength equals Device.Apple)
         randomlyGeneratedDeviceToken.append(validCharacter().toString.charAt(0))
        else
         randomlyGeneratedDeviceToken.append(Random.alphanumeric.head)
        
       randomlyGeneratedDeviceToken.append("\",")
       println(randomlyGeneratedDeviceToken)
       writer.write(randomlyGeneratedDeviceToken.toString())
      

      private def validCharacter(): Int = 
       val a = Random.alphanumeric.head
       if ('0' <= a && a <= '9')
        return (a - '0')
       else if ('a' <= a && a <= 'f')
        return ((a - 'a') + 10)
       else if ('A' <= a && a <= 'F')
        return ((a - 'A') + 10)
       validCharacter() 
     

apple deviceToken 有 64 个字符,因此您需要对其进行 64 次迭代。

【讨论】:

我怀疑这是否可行。您可能已经逆向设计了一个低级验证,它只是检查令牌的正确性在某种程度上。但这只是 Apple 防止任何垃圾邮件的第一道防线。我可以赌一百万美元,你不能在野外向随机的 deviceTokens 发送消息。苹果会很快关闭你。即使它可以与沙盒服务器一起使用,我认为这样的测试也无法证明任何事情。 顺便说一句,没有任何验证?因为从您的代码看来,它只是生成了一个 64 字符长度的 完全随机 十六进制字符的字符串。没有任何限制。 同意 Csaba Toth,这确实会生成随机 64 字符长度的字符串,但验证(请参见上面的有效字符函数)是相同的(我需要分析令牌而不是在网络上的某个地方找到它) apns 最后做了什么,它确实对我测试我的服务器的性能有用。试一试,并尝试将其发送到 apns,它会报告有效。当然,它可能是实际生成的令牌,我们应该礼貌地在沙盒环境中发送它,否则就像你说的那样它会是垃圾邮件。 报告有效是什么意思?仅仅因为 APNS 沙箱服务器使用它并不意味着它是有效的。我认为 APNS 服务器的目标是消耗你扔给它的任何东西,否则它会降低服务用户的性能。然后在引擎盖下,他们可能会破坏令牌。当您请求反馈时,这一切都会在实时 APNS 服务器中显示,并且您将返回无效无效/过期令牌的列表。 您查看的任何用户土地库并不意味着验证与 APNS 服务器所做的验证相同。特别是在查看代码之后,这里没有真正的验证,所有具有给定长度的字母数字随机位串都会通过。库的“验证”仅用于丢弃明显格式错误的 id。

以上是关于Apple 推送通知:发送大量消息的主要内容,如果未能解决你的问题,请参考以下文章

如何发送多行的 Apple 推送通知,即带有 '\n' 字符?

APNS Apple 推送通知服务未收到来自 Apple 的成功消息

Apple 推送通知 - 收货收据

某些设备未收到 Apple 推送通知

来自 APNS(Apple 推送通知服务器)的反馈服务

FCM 是直接发送推送通知还是向 APNS 发送消息?