为啥我与 Apple APNS 的 TCP 连接挂起并强行断开连接

Posted

技术标签:

【中文标题】为啥我与 Apple APNS 的 TCP 连接挂起并强行断开连接【英文标题】:Why does my TCP connection with Apple APNS hangs and forcibly disconnects为什么我与 Apple APNS 的 TCP 连接挂起并强行断开连接 【发布时间】:2017-04-25 10:34:49 【问题描述】:

我正在使用一个很棒的库 PushSharp 将 Apple 和 android 推送通知发送到许多客户端设备。 自上周以来,我们经常面临连接问题。在这些问题之前,我们的托管环境没有更新或发生任何事情。

问题出在ApnsConnection.cs的这一行:

stream.AuthenticateAsClient (Configuration.Host, certificates, System.Security.Authentication.SslProtocols.Tls, false);

有时 TCP 连接会在此处停止响应。大约 21 分钟后,抛出以下异常:

System.IO.IOException: Unable to read data from the connection: 
An existing connection was forcibly closed by the remote host. ---> 
System.Net.Sockets.SocketException: An existing connection was forcibly 
closed by the remote host

PushSharp 的日志显示如下:

13:11:33 | PushServiceV2 | APNS-Client[7]: Sending Batch ID=1, Count=21
13:11:33 | PushServiceV2 | APNS-Client[7]: Connecting (Batch ID=1)
13:11:33 | PushServiceV2 | APNS-Client[7]: client.ConnectAsync
13:11:33 | PushServiceV2 | APNS-Client[7]: client.Client.SetSocketOption
13:11:33 | PushServiceV2 | APNS-Client[7]: SetSocketKeepAliveValues
13:11:33 | PushServiceV2 | APNS-Client[7]: Configuration.SkipSsl:False
13:11:33 | PushServiceV2 | APNS-Client[7]: Create our ssl stream
13:11:33 | PushServiceV2 | APNS-Client[7]: stream.AuthenticateAsClient
13:32:03 | PushServiceV2 | APNS-CLIENT[7]: Send Batch Error: Batch ID=1, Error=System.IO.IOException:

可以看到,“连接被远程主机强制关闭”需要21分钟。

为了解决任何问题,我首先检查在发送一批推送通知后我断开了所有 TCP 连接。我还将批次之间的时间增加到 5 分钟。如果Apple因为我建立了许多连接而断开了我的连接,我想这应该可以解决它。但事实并非如此。

90%的批次都成功收发,所以证书应该是正确的; 我会定期检查反馈服务并删除不活动的设备; 我在不同位置/网络的不同开发机器上遇到了同样的问题。

关于如何进一步调查这个问题有任何线索或提示吗?

提前非常感谢!

【问题讨论】:

【参考方案1】:

我认为我们只是达到了连接数的限制。我已阅读此文档:Troubleshooting Push Notifications 并记下了这一行:

另一种可能是您连接到 APN 的次数过多 并且进一步的连接已被暂时阻止。原样 记录在本地和远程通知编程指南中, 开发人员应该打开一个连接并保持打开状态。如果一个 连接被反复打开和关闭,APNs 会将其视为 拒绝服务攻击和在一段时间内阻止连接

我重写了我的实现和PushSharp 的用法,以便尽可能少地创建和关闭 TCP 连接。它现在运行了几天,没有任何问题。在日志记录中,我看到苹果每天只断开一次连接,PushSharp 很好地重新连接。

【讨论】:

以上是关于为啥我与 Apple APNS 的 TCP 连接挂起并强行断开连接的主要内容,如果未能解决你的问题,请参考以下文章

基于令牌的 APNs 连接错误 400 BadDeviceToken | Apple 推送通知错误

与 APNS gateway.sandbox.push.apple.com 连接 2195 显示空白

为啥 APNS 需要 Entrust ssl 证书的 ssl

socket 如果不关闭会自动关闭吗?为啥要心跳连接?

APNS Apple 推送通知令牌过时并停止工作

通过 PHP 到 APNS 的持久连接