Google AppEngine et le traitement des données

Une des grande capacité des architectures CloudComputing c'est la capacité de scalabilité de celles-ci. Google AppEngine ne déroge pas à la règle, avec une capacité à stocker de gros volumes de données, mais aussi à absorber de grands volumes de connections. Lorsqu'il est nécessaire de traiter des volumes de données importants, pour par exemple mettre à jour une base, ou déclencher des emailing, les temps de process peuvent s'accroître et sortir du cadre d'utilisation classique de la plate-forme. Il y a cependant des solutions pour bien gérer ces problématiques. Elles consistent essentiellement à structurer les accès aux données, et utiliser l'ensemble des outils disponibles. Prenons le cas assez simple d'une table qu'on va parcourir pour mettre à jour des enregistrements. A chaque objet renvoyé par la boucle "for", on enregistre la mise à jour dans la base.

for entity in MyModel.all().filter("color =",
   old_favorite).fetch(100):
   entity.color = new_favorite
   entity.put()

En faisant de cette manière, on fait 1 transaction pour récupérer les 100 enregistrements, puis 1 nouvelle transaction à chaque mise à jour, ce qui nous fait un total de 101 transactions. Dans le système de base de données "Bigtable" de Google Appengine c'est globalement l'appel à l'API qui coute cher. En comparaison avec ce qu'on a pu voir au dessus, il y a une autre façon de réaliser ce traitement :

updated = []
for entity in MyModel.all().filter("color =",
   old_favorite).fetch(100):
   entity.color = new_favorite
   updated.append(entity)
db.put(updated)

Le nombre de transaction chute de manière drastique puisqu'on passe de 101 à 2. L'opération d'enregistrement est beaucuop plus lourde que pouvaient l'être les 101 équivalentes, mais le nombre de call à l'API est réduit à maximum, donc plus efficace. Lorsque de gros volumes de données sont à traiter il peut arriver que le temps de traitement dépasse ce qui est autorisé pour l'exécution d'une requête par Google AppEngine. Depuis la dernière version de Google AppEngine, il est possible de gérer une file d'attente des traitements sur le serveur. Prenons ici l'exemple fourni dans la documentation, il s'agit d'un mailing de masse sur l'ensemble des utilisateurs d'une base. Il y a fort à parier que ce type traitement dépasse très largement dans sa globalité les quelques secondes autorisées pour l'exécution d'une requête. En découpant le traitement en des taches suffisamment petites, et en les mettant dans une file d'attente, ce traitement devient immédiatement scalable.

# for each user, add a task to send a custom email message
for u in users:
   taskqueue.add(url='/work/sendmail',
      params=dict(to=u.email,
         subject='Hello ' + u.name, body='this is a message!'))
return # finished now, emails will be sent offline when tasks execute

# task handler at /work/sendmail, automatically called for each task created above
class MailWorker(webapp.RequestHandler):
   def post(self):
      mail.send_mail('from_me@example.com',
                          self.request.get('to'),
                          self.request.get('subject'),
                          self.request.get('body'))