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'))

Modèles de données de Google AppEngine

Face à la problématique du portage en environnement Google AppEngine d'une application qui doit gérer des volumes de données importantes, il y a quelques bonnes pratiques qu'il faut utiliser absolument. La récente conférence Google IO a été l'occasion de voir une conférence sur le thème de "building scalable application". Les éléments exposés ici ne sont qu'une partie de cette conférence. L'utilisation StringListProperty permet de réduire de manière importante le nombre de Model de données à gérer. Le format de stockage des informations est beaucoup plus dense, et la recherche d'infos est plus simple. La mise en œuvre est très simple, par exemple pour gérer les couleurs favorites d'un utilisateur :

class Favorites(db.Model):
  colors = db.StringListProperty()
  username = db.StringProperty()

fav.colors = ["red", "blue", "green"]

Pour retrouver tous les utilisateurs qui aiment le jaune :

results = db.GqlQuery( "SELECT * FROM FavoriteColors WHERE color = 'yellow'")
users = [r.username for r in results]

Les petites contraintes sont par contre une consommation supérieure de CPU pour la serialisation, et les tris sont un peu plus difficiles à réaliser. Si on compare la façon de laquelle une application de microblogging serait faite avec un outil de base de données classique :

SELECT * FROM Messages INNER JOIN UserMessages 
USING (message_id) WHERE UserMessages.user_id = 'X';

Et maintenant avec App Engine :

class Message(db.Model):
  sender = db.StringProperty()
  receivers = db.StringListProperty()
  body = db.TextProperty()

results = db.GqlQuery("SELECT * FROM Message WHERE receivers = :1", me)

C'est tout de suite plus simple ! Par contre si les propertylist sont de très grande tailles (plus de 100 items) les performances peuvent être fortement affectées. La solution dans ce cas est de couper l'enregistrement en deux en mettant la liste d'un coté, et les données de l'autre. En SQL ceci nécessiterait de réaliser une complexe jointure entre les 2 tables mais ici c'est immédiatement plus simple.

class Message(db.Model):
  sender = db.StringProperty()
  body = db.TextProperty()

class MessageIndex(db.Model):
  receivers = db.StringListProperty()

indexes = db.GqlQuery("SELECT __key__ FROM MessageIndex WHERE receivers = :1", me)
keys = [k.parent() for k in indexes]
messages = db.get(keys)

Voila pour cette rapide introduction aux structures de données de l'AppEngine. Si il y a vraiment un point qu'il ne faut pas oublier lorsqu'on utilise des outils de type CloudComputing c'est bien la scalabilité. Avec ces bonnes pratiques, c'est bien de toute l'expérience de Google sur le sujet  que vous aller pouvoir profiter .

TwittBourse, le twitter du CAC40

Après quelques semaines de développement et de test, enfin je lance Twittbourse. Ce service a vocation à fournir des infos régulières sur la place boursière de Paris par le biais d'un compte twitter dédié. Pour profiter du service rien de plus simple, il suffit de suivre le compte twitter @twittbourse, ou de se rendre sur www.twittbourse.com (bit.ly/cac40).

Media_httpwwwvhe74com_melsc
Au fil de l'eau dans la timeline apparaitrons les principales hausses et baisses du CAC40. Toutes les 1/2 heures un Tweet permet d'avoir ces informations majeures. Dans de futures évolutions les faits marquants de l'économie et les événements financiers majeurs seront aussi relatés dans cette timeline. La vocation du service est de fournir une agrégation de flux d'informations. Par ailleurs il est aussi envisagé d'offrir à des utilisateurs la possibilité de suivre une liste de valeurs personnalisées dans leur Twitter. Nous reviendrons ultérieurement sur ces évolutions du service à venir. Pour ce qui est de la technique qui est là dessous, ce projet était l'occasion de tester grandeur nature les capacité de Google App Engine. Autant la philosophie de l'outils avec son approche cloudcomputing est attrayante, que par contre la mise en oeuvre peut parfois réserver des surprises. Pour ce developpement je me suis basé sur l'implémentation Python de GAE. Les performances ne sont malheureusement pas au rendez-vous quand il s'agit d'aller chercher des volumes de données importants et de les insérer dans la système de stockage de données de Goggle. Il y a par contre des choses intéressantes comme les outils de développement, le dashboard pour surveiller l'appli en exploitation qui sont très bien faites, tout comme l'ensemble de l'infrastructure. On reviendra assez rapidement sur la plateforme. Il vous reste maintenant à suivre @twittbourse, et à échanger pour faire grossir la communauté, pleins de choses devraient venir..... stay tuned.

Google AppEngine : Le rendu de pages HTML

Après avoir regardé la structure générale du framework et l'organisation des fichiers, nous avons regardé la structure applicative. Cette fois ci nous allons nous atttaquer à un gros morceau puisque nous allons évoquer ensemble le moteur de rendu des pages HTML. Ceux qui sont habitués aux appli web développées en Python ne vont pas trop être surpris puisque Google s'est appuyé sur le reconnu Django. Nous allons passer en revue le fonctionnement de ce moteur, mais je vous recommande d'aller voir la documentation de Django pour approfondir le sujet. Après avoir fait donc ce rendu de base on va maintenant regarder comment créer des blocs de rendu, avec une possiblité d'organiser le code, et de réutiliser facilement celui-ci.

Google App Engine : HelloWorld !

Dans le précédent post je vous avait présenté Google App Engine dans sa globalité, afin de positionner ce framework de développement. Maintenant nous allons entrer plus en détail avec la mis en oeuvre d'un petite application. Au titre vous aurez compris que tout ça va rester trivial pour le moment ! Pour aller un peu plus loin il peut être utile de structurer un peu le code et de pouvoir le décomposer en modules. Ici aussi rien d'extraordinaire, seulement des choses simples, que nous allons découvrir pas à pas. 

 

Google App Engine

Ce post est le premier d'une série sur google App Engine le moteur d'exécution d'application de google en mode cloud computing. Ce framework s'appuie sur Python, langage largement utilisé sur les frontaux web de Google, et permet de déployer des applications sur les serveurs de Google. Tout ceci est d'une pris en main très rapide, même si vous n'avez pas de réelle expérience de Python. Je vous laisse découvrir ça. Principaux liens :

Quelles plateformes utiliser ?

Ici volontairement je vais pas parler de langage mais plutôt de plate-forme, quand on commence à parler d'une application. Les langages vont se caractériser par plusieurs point que sont leur complexité, le spectre fonctionnel couvert (éventuellement par des frameworks disponibles), et leur facilitée de mise en oeuvre. Comme beaucoup de monde j'utilise depuis la nuit des temps des outils basés sur du php pour mes plate-formes (wordpress, dotclear, frontaux d'accès à des bases de données... ), j'ai utilisé de manière ponctuelle Ruby-on-rails, et maintenant je m'aperçois que python est de plus en plus utilisé. L'une des différences ente ces approches est principalement due au fait que d'un coté on a des langages simples plus ou moins généralistes et que de l'autre on se retrouve avec des frameworks complet beaucoup plus rigides. Le PHP à plusieurs avantages, c'est un langage qui est dédié à la création de pages web. Ceci permet une grande souplesse dans la création sur un mode itératif, mais a comme corollaire de permettre de rendre le produit rapidement non maintenable. En effet cette approche ne favorise pas la séparation des éléments d'interface des éléments de code, a moins là aussi de mettre en oeuvre un framework. Les expériences que j'ai pu avoir de reprise de code après de longue périodes de production ont été assez dramatiques.Un autre avantage de PHP c'est son universalité, qui permet de facilement déployer les pages sur des hébergements simples. Bref PHP c'est idéal pour les petits projets, même si de grosses infrastructures l'utilisent. RUBY ON RAILS est un framework complet construit autour du langage ruby. ce framework a comme gros avantages de facilement séparer la logique, du contenu, et de la présentation. En effet tout est formalisé au travers d'une architecture Model/Vue/Controller. Cette structuration apporte un indéniable confort dans le développement, permet de facilement structurer le développement en équipe, et apporte une capacité de maintenance du code incomparable. On retrouve un peut la démarche qu'on a par ailleurs avec une architecture J2EE, tout en étant plus abordable quand même. ROR permet une rapidité de création incomparable tant qu'on reste dans les limites du framework. Si on s'intéresse à des architecture de type interfaces riches (Flex, Air, Sylverlight), alors le découplage logique / présentation présente un intérêt non négligeable. Le gros défaut de ROR est qu'aujourd'hui les compétences sur le sujet sont assez limitées, et que lorsque la phase de maquette est terminée il faut déployer obligatoirement sur une infrastructure de type dédiée donc nécessairement avec une charge d'administration plus élevée. Récemment je me suis intéressé  à Python, ayant vu que c'était le langage utilisé par Google pour son app engine, j'ai un peu plus creusé sur ce sujet. Aujourd'hui chez Google trois langages sont utilisés : C++, Java, Python. Python sert aussi bien en interne, qu'en externe pour réaliser toutes les chaînes de traitement, réaliser tout le packaging d'application, etc... Bref on est en présence d'un langage relativement structuré, donc suffisamment directif pour permettre de produire avec une certaine qualité, et d'être suffisamment versatile en termes d'usages. Il y a une communauté, et des sources d'informations importantes autour de ce langage, et le dernier point, et pas des moindres, c'est la disponibilité en offres d'hébergement, qui peut donc en faire une plate-forme non négligeable pour déployer des applications de taille moyenne. Même si aucun choix sur ce sujet ne peut être définitif, je pense qu'il y a des pistes intéressantes à surveiller.