GCM消息传递时间极不稳定

15

我已经使用了GCM支持设置了一个Android应用,并且有一个小型的测试应用程序,可以向该应用程序发送消息。

当我在模拟器中运行应用程序时,通过日志消息可以看到它向GCM注册并获得了一个令牌。

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

有时消息几乎立即出现,有时需要20分钟。上周五,我的两个测试消息用了15和20分钟。今天早上发送的前两个消息立即出现,但下一个消息还没有出现——只过了10分钟...

是否有任何措施可以使交付时间保持一致地快速?20分钟的随机延迟将是一个无法接受的条件。


1
我也注意到了这种行为,我认为这是通过Wi-Fi连接时的某种10分钟超时。我已经在Google Group上发布了相关信息,但目前还没有回应:https://groups.google.com/d/msg/android-gcm/Y33c9ib54jY/vmJRFv0SmKYJ - Rupert Rawnsley
5个回答

29

我们遇到了相同的问题,但这个问题因网络而异。我们认为这是由于家用路由器(Virgin Super Hub)在闲置五分钟后断开连接导致的。您可以通过每两分钟发送一条空的GCM消息来确认保持连接。

以下是我们所做的更详细的解释:https://groups.google.com/d/msg/android-gcm/Y33c9ib54jY/YxnCkaPRHRQJ


2
Rupert Rawnsley,您已经对GCM延迟问题进行了一些出色的研究,并在上面的Google Group链接中发表了。这应该得到更多的赞同。 - HitOdessit

4
这确实是由Google Cloud Messaging中不现实的心跳间隔引起的。
这可能是GCM中最令人沮丧的错误。 GCM通过在Android设备与Google服务器之间维护空闲的套接字连接来工作。这很好,因为它几乎不会消耗电池电力(与轮询相反),并且允许设备在消息到达时立即唤醒。为了确保连接保持活动状态,Android将在移动连接上每28分钟发送一个心跳,在WiFi上每15分钟发送一个心跳。如果心跳失败,则已终止连接,并且GCM将重新建立连接并尝试检索任何待处理的推送通知。心跳间隔越长,消耗的电池电量越少,设备被唤醒的次数也越少。
然而,这是以巨大的代价为代价的:心跳间隔越长,识别损坏的套接字连接所需的时间就越长。在部署GCM之前,Google没有彻底测试这些间隔在实际情况下的使用情况。这些间隔的问题是由网络路由器和移动运营商引起的,他们在几分钟的不活动后断开空闲的套接字连接。通常,这在廉价家用路由器中更为常见,其制造商决定空闲套接字连接的最大寿命,并将其终止以节省资源。这些路由器只能处理有限数量的并发连接,因此采取这种措施以防止过载。这导致终止GCM套接字,当到达传递GCM消息的时间时,消息无法到达设备。设备只会在发送心跳时(在0-28分钟后)意识到连接已断开,在某些情况下(例如消息具有时间关键性)使推送通知无效。根据我的经验,大多数廉价路由器在不活动5-10分钟后终止空闲连接。
我写了一篇完整的帖子,讨论了这个问题和其他GCM问题: http://eladnava.com/google-cloud-messaging-extremely-unreliable/ Google Cloud Messaging的替代品 Pushy (https://pushy.me/) 是一个独立的推送通知网关,完全独立于GCM。它保持自己的后台套接字连接,就像GCM一样,以接收推送通知。底层协议是MQTT,这是一种极轻量级的发布/订阅协议,使用非常少的网络带宽和电池电量。
Pushy的巨大优势在于,从服务器发送推送通知(到设备)和注册设备以接收推送通知的代码实际上可以在GCM和Pushy之间相互替换。这使得在实现GCM并不得不放弃其不稳定性后轻松切换到Pushy。
(免责声明:我为自己的项目创立了Pushy,并意识到许多应用程序将受益于此服务。)

4
您无法保证快速交付,因为正如CommonsWare所指出的那样,GCM与设备的连接可能很差。然而,在交付过程中可能会有两种延迟:1)GCM连接到手机(如前所述),以及2)消息实际从GCM服务器发送出去的延迟。如果您在发送应用程序中将“time_to_live”参数设置为0秒,则至少可以测试延迟发生的位置。
0秒的值意味着消息将立即发送,如果交付失败,则消息将在GCM服务器上被丢弃。这对于实际使用来说不是一个实用的值,但可以让您找出交付过程中哪个部分导致了延迟。

既然我在我们的服务器上记录了发送消息到GCM的调用,这主要会告诉我GCM是否在连接设备时出现问题,对吗? 我得试试。 - CasaDelGato
如果手机没有立即收到消息,则带有TTL为0的确认,那么GCM服务器与手机之间没有连接。然后它将放弃并永远不会再尝试发送该消息。 - NickT
2
测试TTL=0和TTL=1天并没有产生任何区别。有时消息会立即显示,有时则需要很长时间。(好吧,使用TTL=0,消息可能根本不会显示。)当设备在线且活动时,出现随机的15-20分钟延迟,使得GCM似乎相当不可靠,并且用户体验极差。(你认为有人发短信愿意等待20分钟才能收到他的消息吗?) - CasaDelGato
当数据连接良好时,我可以立即收到消息。上个周末在数据连接较差的地方(不在伦敦),需要等待很长时间才能收到消息。如果我在设备上禁用数据包,然后立即重新启用它,所有消息都会立即传送。我认为这是我的Galaxy S2在从H+切换协议到H或3G时出现了错误。 - NickT
除了 TTL 之外,还要注意在将 GCM 通知发布到 GCM 服务器时设置的“delay_while_idle”参数。这将使得 Google 只在设备退出空闲状态后才传递通知。 - Roberto Andrade

2
据报道,GCM 在保持活动心跳方面存在相当严重的问题,不太可靠。因此,由于它在 3G 下只有每 15 分钟(在 Wifi 下为 28 分钟)调度一次,如果出现某些原因导致服务器连接中断,可能需要等待几分钟才能恢复。
这种情况促使开发一种解决方案,不依赖于第三方网络,向离线(后台运行)Android 应用程序提供大规模可靠的推送通知。

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


0

这件事对我很重要。

我已经在一个一秒定时器处理程序中设置了这段代码,以便每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是否停止。

已经工作了几天,似乎没问题。


如果您每2分钟发送一次GCM,那么它不会消耗前端实例小时数吗? - Dexter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接