GCM Advanced Topics

Ce document couvre des sujets avancés pour GCM.

Durée de vie d'un message (Lifetime of a Message)

Quand un serveur tiers envoi un message à GCM et reçoit un ID message en retour, cela ne signifie pas que le message a déjà été fourni à l'appareil. Cela signifie plutôt qu'il a été accepté pour être délivré. Ce qu'il advient du message après qu'il a été accepté dépend de nombreux facteurs.

Dans le meilleur scénario, si l'appareil est connecté à GCM, avec l'écran allumé, et sans restrictions d'étranglement, le message sera délivré immédiatement.

Si l'appareil est connecté mais en veille, le message sera toujours délivré immédiatement a moins que l'attribut delay_while_idle est définit à true. Sinon, il sera stocké dans les serveurs GCM jusqu’à ce que l'appareil soit éveillé. Et c'est ici que l'attribut collapse_key joue un rôle : s'il y a déjà un message avec la même clé de pliage/réduction (et ID d'enregistrement) stocké et en attente de livraison, l'ancien message sera ignoré et le nouveau message prendra sa place (autrement dit, l'ancien message est remplacé par le nouveau). Cependant, si la clé de réduction n'est pas définie, les deux message (le nouveau et l'ancien) sont stockés pour une livraison future. Les messages pliables sont aussi nommés send-to-sync messages.

Note : Il y a une limite sur le nombre de message qui peuvent êtres stocké sans pliage. Cette limite est actuellement de 100. Si la limite est atteinte, tous les messages stockés sont éliminés. Puis, quand l'appareil se reconnecte, il reçoit un message spécial indiquant que la limite a été atteinte. L'application peut ainsi traiter la situation proprement, généralement en demandant une synchronisation complète.

Également, il y a une limite sur le nombre de collapse_key que vous pouvez avoir par appareil. GCM autorise un maximum de 4 clefs de pliage a utiliser avec le serveur GCM par appareil tout le temps. En d'autres mots, le serveur GCM peut stocker simultanément 4 messages send-to-sync, chacun avec une clé de pliage différente. Si vous excédez ce nombre, GCM gardera seulement 4 clefs de pliage, sans garantie sur quelles clés il y aura.

Si l'appareil n'est pas connecté à GCM, le message sera stocké jusqu'à ce qu'une connexion soit établie (toujours avec les règles des clé de pliage). Quand une connexion est établie, GCM livrera à l'appareil tous les messages en attente, quel que soit l'attribut delay_while_idle. Si l'appareil ne se reconnecte jamais (par exemple, si elle remise à zéro d'usine), le message expirera et sera écarté du stockage GCM. Le temps d'expiration par défaut est de 4 semaines, a moins que l'attribut time_to_live soit défini.

Pour finir, quand GCM tente de livrer un message à un appareil et que l'application a été désinstallée, GCM rejettera ce message tout de suite et invalidera l'ID d'enregistrement. Les prochaines tentatives pour envoyer un message à cet appareil auront une erreur NotRegistered.

Bien qu'il ne soit pas possible de suivre le statut de chacun des messages, les stats de Console Google Cloud sont ventilés par les messages envoyés à l'appareil, les messages pliables et les messages en attente.

Étranglement (Throttling)

Pour éviter les abus (tels que l'envoi d'un flot de message à un appareil), et pour optimiser l'efficacité globale du réseau et la vie de la batterie de l'appareil, GCM implémente l’étranglement des messages en utilisant un système de seau à jetons. Les messages sont étranglés par application et par clé de pliage de base (incluant les les messages non pliables). Chaque clé de pliage d'application est accordée par les jetons initiaux, plus de nouveaux jetons sont par la suite accordés. Chaque jeton est valide pour un seul message envoyé à l'appareil. Si une application épuise sont stock de jetons disponibles, les nouveaux messages stockés dans une file d'attente jusqu'à ce que de nouveaux jetons soient disponibles au moment de l'accord périodique. Ainsi l'étranglement entre les périodes d'accord peut ajouter de la latence à la transmission du message pour une application qui envoie un grand nombre de message dans un court laps de temps.

Conserveur le statut d'enregistrement synchronisé (Keeping the Registration State in Sync)

Chaque fois que les applications s'enregistrent, il doit enregistrer l'ID d'enregistrement pour une utilisation ultérieure, la passer au serveur tiers pour compléter l'enregistrement, et suivre si le serveur a complété l'enregistrement. Si le serveur échoue l'enregistrement, il doit essayer à nouveau ou annuler l'enregistrement de GCM.

Il y a aussi deux autres scénarios nécessitant une attention spéciale :

  • Mise à jour d'application
  • Backup et restauration

Quand l'application est mise à jour, elle doit annuler son ID d'enregistrement existant, comme il n'est pas garanti pour fonctionner avec la nouvelle version. Parce qu'il n'y pas de méthode cycle de vie appelée lorsque l'application est mise à jour, la meilleure méthode pour réaliser cette validation est en stockant la version courante de l'application quand un ID d'enregistrement est stocké. Puis quand l'application est démarrée, comparer la valeur enregistrée avec la version courante de l'application. Si elles ne correspondent pas, invalider la donnée stockée et relancer le processus d'enregistrement.

Similairement, vous devriez pas enregistrer l'ID d'enregistrement quand l'application est backupée. Ceci car le "regID" pourrait devenir invalide du temps que le l'application soit restaurée, ce qui mettrait l'application dans un état invalide (l'application se croit enregistrée, mais le serveur et GCM n'ont plus ce regID - donc l'application n'obtiendrait plus de messages).

IDs canoniques

Sur la partie serveur, aussi longtemps que l'application se comporte bien, tout devrait fonctionner normalement. Toutefois, si un bug dans l'application déclenche des inscriptions multiples pour le même appareil, il peut être difficile de concilier l'état et vous pourriez vous retrouver avec des messages en double.

GCM fourni une installation nommée "canonical registration IDs" pour se sortir facilement ces situations. Un regID canonique est défini pour être l'ID du dernier enregistrement demandé par votre application. C'est cet ID que le serveur devrait utiliser lors de l'envoi de message à l'appareil.

Si plus tard vous essayer d'envoyer un message en utilisant un regID différent, GCM traitera la demande comme d'habitude, mais il incluera dans la réponse le regID canonique dans le champs registration_id. Soyez sûrs de remplacer le regID stocké fans votre serveur par ce regID canonique, que finalement l'ID que vous utilisez va arrêter de fonctionner.

Automatic Retry Using Exponential Back-Off

Lorsque l'enregistrement ou la désinscription échoue, l'application devrait recommencer l'opération a échoué.

Dans le cas le plus simple, si votre application tente d'enregistrer et GCM est pas un élément fondamental de l'application, l'application pourrait simplement ignorer l'erreur et réessayez d'enregistrer le prochain démarrage. Sinon, il faut recommencer l'opération précédente en utilisant exponentielle back-off. En exponentielle back-off, chaque fois qu'il ya un échec, il faut attendre deux fois le montant précédent de temps avant d'essayer de nouveau. Si l'opération d'enregistrement (ou annulation) était synchrone, il pourrait être rejugé dans une boucle simple. Cependant, comme il est asynchrone, la meilleure approche est de programmer un PendingIntent pour recommencer l'opération.

Send-to-Sync vs. Messages with Payload (charge utile)

Tout message envoyé à GCM a les caractéristiques suivantes :

  • une limite de charge utile de 4096 bytes (4ko)
  • par défaut, il est stocké par GCM durant 4 semaines

Mais malgré leurs similitudes, les messages peuvent se comporter très différemment en fonction de leurs contextes particuliers. Une des grandes différences entre les messages est de savoir si elles sont pliables (où chaque message remplace le précédent) ou non pliable (où chacun des messages est délivré). Tout message envoyé à GCM est soit un message (pliable) "send-to-sync" ou un "message with payload" (non pliable).

Send-to-sync messages

Un message "send-to-sync" est souvent un "chatouillement" qui indique à l'application mobile de synchroniser ses données depuis le serveur. Par exemple, supposez que vous avez une application mail. Quand un utilisateur reçoit un nouveau mail sur le serveur, le serveur ping le mobile avec un message "nouveau mail". Cela dit à l'application de se synchroniser avec le serveur pour récupérer le nouveau mail. Le serveur pourrait envoyer ce message de multiples fois tant que des mails continuent de s'accumuler, avant que l'application ait eu la chance de se synchroniser. Mais si l'utilisateur a reçu 25 nouveaux mails, il n'y a plus lieu de conserveur chacun des messages "nouveau mail". Un seul est suffisant. Un autre exemple serait une application sportive qui met à jour les utilisateurs avec les derniers scores. Seul le dernier message récent est nécessaire, donc cela à du sens de de remplacer les anciens messages avec le dernier.

Les applications de mail et de sport sont des cas où vous utiliseriez le paramètre collapse_key de GCM. Une clé pliable est une string arbitraire utilisée pour réduire un groupe de messages, comme lorsque le smartphone est déconnecté, comme cela seulement le dernier message récent est envoyé au client. Par exemple "nouveau mail", "mise à jour disponible", et ainsi de suite.

GCM autorise un maximum de 4 clés de pliage différentes à être utilisé par le serveur de GCM à un moment donné. En d'autres termes, le serveur de GCM peut simultanément enregistrer 4 messages différents send-to-sync par dispositif, chacune avec une clé de pliage différente. Par exemple, Appareil A peut avoir A1, A2, A3, et A4. Appareil B peut avoir B1, B2, B3, et B4, et ainsi de suite. Si vous excédez le nombre, GCM gardera uniquement 4 clés sans garantie des quelles seront conservées.

Messages with payload

Contrairement aux messages "send-to-sync", chaque "message with payload" (non pliable) est délivré. La charge utile est limitée à 4 ko. Par exemple, ici un message formaté JSON dans une application dans laquelle les spectateur parlent d'événement sportif :

{
  "registration_id" : "APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...",
  "data" : {
    "Nick" : "Louis",
    "Text" : "bon match !",
    "Room" : "FranceVSEspagne",
  },
}

Un "message with payload" n'est pas simplement un "ping" vers l'application mobile pour contacter le serveur pour rapatrier de la donnée. Dans l'application de sport mentionnée, par exemple, vous voulez livrer chacun des messages, car chaque message a un contenu différent. Pour spécifier un message non pliable, il faut simplement ne pas renseigner l'attribut collapse_key. Ainsi GCM enverra chaque message individuellement. Note : l'ordre de livraison n'est pas garanti.

GCM enregistrera jusqu'à 100 messages non pliable. Après cela, tous les messages seront ignorés de GCM, et un nouveau message est créé qui indique au client comment il est loin derrière. Le message est remis à travers une intention régulière com.google.android.c2dm.intent.RECEIVE avec l'extra message_type, dont la valeur est toujours la chaîne "deleted_messages".

L'application doit répondre par la synchronisation avec le serveur pour récupérer les messages rejetés.

Que dois-je utiliser ?

Si votre application ne nécessite pas de message non pliable, les messages pliables sont un meilleur choix d'un point de vue de performances, parce qu'ils sont moins lourds sur la batterie de l'appareil. Toutefois, si vous utilisez des messages pliables, souvenez vous que GCM ne permet qu'un maximum de 4 messages pliables différents pour être utilisé par dispositif à un moment donné. Vous ne devez pas dépasser ce nombre, ou il pourrait avoir des conséquences imprévisibles.

Définition d'une date d'expiration pour un message

La fonctionnalité durée de vie (Time to Live - TTL) permet a l’émetteur de spécifier la durée de vie maximum d'un message en utilisant le paramètre time_to_live. La valeur du paramètre doit être une durée entre 0 et 2 419 200 secondes qui correspond à la période maximum pour laquelle GCM enregistrera et essayera de livrer le message. Les demandes qui ne contiennent pas ce champ auront pas défaut une durée maximum de rétention de 4 semaines.

GCM délivre généralement les messages immédiatement après leur envoi. Toutefois, cela pourrait ne pas être toujours possible. Par exemple, le dispositif peut être éteint, hors ligne, ou autrement indisponible. Dans d'autres cas, l'expéditeur lui-même peut demander que les messages ne soient pas livrés avant que l'appareil soit activé en utilisant l'attribut delay_while_idle. Enfin, GCM pourrait retarder intentionnellement des messages pour empêcher une application de consommer trop de ressources et un impact négatif sur la vie de la batterie.

Lorsque cela se produit, GCM va stocker le message et de le livrer dès qu'il est possible. Bien que ce soit très bien dans la plupart des cas, il ya des applications pour lesquelles un message tardive peut ainsi jamais être livré. Par exemple, si le message est une notification d'appel entrant ou de chat vidéo, il n'a de sens que pour une petite période de temps avant que l'appel soit terminé. Ou si le message est une invitation à un événement, il sera inutile si elle est reçue après que l'événement soit terminé.

Un autre avantage de préciser la date d'expiration pour un message est que GCM n'étranglera jamais les messages avec une valeur time_to_live de 0 secondes. En d'autres termes, GCM garantira le meilleur effort pour les messages qui doivent être livrés "maintenant ou jamais". Gardez à l'esprit que la valeur time_to_live de 0 signifie que les messages ne peuvent être livrés immédiatement seront rejetées. Cependant, parce que ces messages ne sont jamais stockées, cette offre le meilleur temps de latence pour l'envoi des notifications.

Ici, un exemple de demande JSON avec TTL :

{
  "collapse_key" : "demo",
  "delay_while_idle" : true,
  "registration_ids" : ["xyz"],
  "data" : {
    "key1" : "value1",
    "key2" : "value2",
  },
  "time_to_live" : 3
}

GCM regID expired changed

Ressources