GCM消息传递时间非常不稳定

我已经设置了一个支持GCM的Android应用程序,并且有一个小测试应用程序可以向应用程序发送一个消息。 当我在模拟器中运行App时,我可以看到(通过记录msgs)它向GCM注册并获取令牌。

然后,当我将令牌放入我的测试应用程序并让它发送一个消息时,结果显示发送了1个消息,0个失败,0个更改了ID。

有时,msg几乎立即出现,有时需要20分钟。 星期五,我的2个测试消息花了15分钟和20分钟。 我今天早上发送的前2个是立即的,下一个还没有出现 – 它只有10分钟……

有什么办法可以让交货时间一直很快吗? 随机的20分钟延迟将是一个非常不可接受的条件。

我们遇到了同样的问题,但它从网络到网络各不相同。 我们认为这是家庭中枢路由器(Virgin Super Hub)在五分钟不活动后断开连接。 您可以通过每两分钟发送一个空的GCM消息进行确认,以保持连接处于活动状态。

以下是对我们所做工作的更深入解释: https : //groups.google.com/d/msg/android-gcm/Y33c9ib54jY/YxnCkaPRHRQJ

您无法保证快速交付,因为GCM到设备的连接可能很差,因为CommonsWare指出。 但是,在传送列车中有两种可能的延迟:1)GCM连接到电话(如前所述)和2)实际从GCM服务器发送的消息延迟。 如果在发送应用程序中将’time_to_live’参数设置为0秒,则至少可以测试延迟发生的位置。

值为0秒表示将立即发送消息,如果传递不成功,则将在GCM服务器上丢弃该消息。 它对于现实生活使用并不具有实用价值,但可以让您找出交付列车的哪个部分导致延误。

据报道,GCM存在一个非常严重的问题,即保持心跳不能如此可靠。 因此,由于它仅每15分钟(超过3G)或28分钟(通过Wifi)发送一次,如果由于某种原因服务器连接被丢弃,则可能无法在几分钟内恢复。

这些types的恶作剧促使开发出一种解决方案,该解决方案不依赖第三方网络为离线(后台)Android应用程序提供大规模可扩展且可靠的推送通知。

https://help.pubnub.com/entries/21720011-Can-my-Android-App-Receive-Messages-While-Inactive

这确实是由Google Cloud Messaging中不切实际的心跳间隔引起的。

这可能是GCM中最令人沮丧的错误。 GCM通过维护从Android设备到Google服务器的空闲套接字连接来工作。 这很好,因为它几乎不消耗电池电量(与轮询相反),并且它允许在消息到达时立即唤醒设备。 为了确保连接保持活动状态,Android将在移动连接上每28分钟发送一次心跳,在WiFi上每15分钟发送一次心跳。 如果心跳失败,则连接已终止,GCM将重新建立连接并尝试检索任何挂起的推送通知。 心跳间隔越高,消耗的电池越少,设备从睡眠中唤醒的次数就越少。

但是,这需要付出很大的代价:心跳间隔越长,识别断开的套接字连接所需的时间就越长。 在部署GCM之前,Google尚未在实际情况中彻底测试这些时间间隔。 这些间隔的问题是由网络路由器和移动运营商引起的,他们在几分钟不活动后断开空闲套接字连接。 通常,这在廉价的家用路由器中更常见,其制造商决定空闲套接字连接的最大寿命,并终止它以节省资源。 这些路由器只能处理有限数量的并发连接,因此采取这种措施来防止过载。 这导致终止GCM套接字,并且当需要传递GCM消息时,它不会到达设备。 设备只会在0到28分钟后发送心跳时才会意识到连接已断开,导致推送通知在某些情况下无效(例如,当消息对时间要求严格时)。 根据我的经验,大多数便宜的路由器在大约5-10分钟不活动后终止空闲连接。

我写了一篇关于这个和其他GCM问题的完整post:

http://eladnava.com/google-cloud-messaging-extremely-unreliable/

Google Cloud Messaging的替代方案

Pushy( https://pushy.me/ )是一个独立的推送通知网关,完全独立于GCM。 它保持自己的后台套接字连接,就像GCM一样,用于接收推送通知。 底层协议是MQTT,一种极轻量级的pub / sub协议,利用非常少的网络带宽和电池。

Pushy的一个巨大优势是,用于发送推送通知(来自服务器)以及注册设备以进行推送通知的代码实际上可以在GCM和Pushy之间互换。 这使得在实施GCM之后切换到Pushy变得非常容易,并且由于其不稳定而不得不放弃它。

(完全披露:我为自己的项目创立了Pushy,并意识到许多应用程序将从这样的服务中受益)

这件事对我很重要。

我在一秒计时器处理程序中设置了此代码,每2分钟发送一条GCM消息。 希望是它能保持活力

if ((mOneSecondTick %120) == 0){ // q 1 minute check when we got last call.... long lDiff = System.currentTimeMillis() - GCMlastCall; if (PushAndroidActivity.GCMAvailable){ Log.d("pushAndroidActivity",String.format("(mOneSecondTick %d",lDiff)); if (lDiff > 122 * 1000){ // more than a minute Intent intent = new Intent(StayInTouch.this,PushAndroidActivity.class); 2startActivity(intent); }else{ // every 2 minutes send out a gcm message... asyncWebCall(String.format(AgeingLib.GCMTICKLE,androidid),0); return; // only if it sends a tickle and all is well... } }else{ Log.d("pushAndroidActivity",String.format("(mOneSecondTick mod60 no GCM on this device")); } } 

GCMlastCall是最后一次收到消息,因此我们可以判断gcm是否已停止。

工作了几天现在看来还可以

有什么办法可以让交货时间一直很快吗?

在生产中,交付时间将变化很大,因为移动设备是移动的,因此具有可变的连接性,超出GCM本身内的任何交付问题。