Formation Google App Engine

51
Google App Engine Formation pratique Février, 2013 Formation animée par: RHANIZAR Abdelhakim

description

Développer une application sur le Cloud avec Google App Engine Formation animée par Rhanizar Abdelhakim

Transcript of Formation Google App Engine

Page 1: Formation Google App Engine

Google App Engine Formation pratique

Février, 2013

Formation animée par: RHANIZAR Abdelhakim

Page 2: Formation Google App Engine

Objectifs de la formation

• Se familiariser avec les services de GAE et son DataStore• Savoir les contraintes liées au développement sur GAE• Développer et déployer en Live des applications Web sur

l’infrastructure GAE• Avoir suffisamment de connaissance pour passer à la vitesse

supérieure

2

Page 3: Formation Google App Engine

Sommaire

I. Présentation générale

II. Services offerts par GAE

III. Persistance dans GAE

IV. Web services Rest dans GAE

* Code Lab après chaque partie

3

Page 4: Formation Google App Engine

A propos de moi

• RHANIZAR Abdelhakim• Ingénieur d’état en informatique• Spécialiste du Cloud Computing & RIA

4

[email protected]

@a_rhanizar

Page 5: Formation Google App Engine

Première partie

GAE: Présentation générale

5

Page 6: Formation Google App Engine

Google App Engine

• Plateforme (PaaS) pour développer et déployer des applications Web sur l’infrastructure de Google

• Support des RunTime Java (JRuby, Groovy, Scala...), Python et Go• Réutilisation de la plupart des API -Java- standards (Servlet/JSP ,

Mail, JPA, JDO..) et des frameworks populaires (Struts 2, Spring MVC, …)

• Quotas gratuits puis Pay-As-You-Go

6

Page 7: Formation Google App Engine

GAE: Avantages

• Infrastructure haut de gamme de Google• Flexibilité/Scalabilité automatique• Réduction du Time to marquet• Plus d’agilité• Quota gratuit généreux• Pay per Use• 99.95 SLA

7

Page 8: Formation Google App Engine

Etat de santé de GAE

• http://code.google.com/status/appengine -> A suivre!• [email protected] -> A adhérer!

8

Page 9: Formation Google App Engine

GAE: Architecture et fonctionnement

9

RPC calls

Services Cluster 2

Services Cluster 1MemCache Task Queue

MemCache

MemCacheTask Queue

MemCache

Frontend 1

Frontend 2

Backend 1

Backend 2

Frontend 1

Frontend 2

Backend 1

Backend 2

Backend N

Page 10: Formation Google App Engine

Sandbox

• Environnement qui isole l’exécution des applications GAE et facilite leur sclabilité pour Google

• Plusieurs restrictions imposées sur les threads• Une application GAE ne peut pas:

Ecrire dans un fichier système (java.io.FileWriter) Accéder à un fichier qui n’a pas créé Communiquer avec l’extérieur sans passer par les API de GAE

(Sockets, HttpClient) Faire des appels système (java.lang.System)

• Liste des classes Java autorisées: https://developers.google.com/appengine/docs/java/jrewhitelist

10

Page 11: Formation Google App Engine

Frontend Vs Backend instances11

Fonctionnalité Frontend Backend

Limites 60 sec maxi par requête HTTP10 min maxi par tâche/job

100 API call simultanés par requête HTTP24h maxi / job

CPU Flexible, facturé à l’usage Configurable 400 MHz – 4.8 GHz

Mémoire 128 Mb Configurable 128 Mb – 1 Gb

Volatilité Instances volatiles/dynamiques

Configurable ( Résident + dynamique )

Accessibilité Instance anonyme Accessible via une URLhttp://instance.backend_name.your_app_id.appspot.com

Scalabilité Automatique (GAE Scheduler) Configurable

Requêtes simultanées

Off par défaut, 10 maxi Oui, le nombre de requêtes maxi est configurable

Page 12: Formation Google App Engine

Prix des instances Backend

Classe RAM CPUTarif horaire d’une instance

Tarif mensuel d’une instance

B1 128MB 600MHz $0.08 $57.60

B2 (Par défaut) 256MB 1.2GHz $0.16 $115.20

B4 512MB 2.4GHz $0.32 $230.40

B8 1024MB

4.8GHz $0.64 $460.80

12

Avez-vous vraiment besoin d’utiliser des instances Backend?

Bonne pratique: Exécuter les traitements lourds dans des tâches (queue) -> 10 min/tâche au lieu de 1min/requête!

Page 13: Formation Google App Engine

Le scheduler GAE

• C’est un service qui décide comment traiter une requête d’un utilisateur:1. La faire servir par une instance Idle

2. Lancer une nouvelle instance pour la servir

3. Attendre la libération d’une instance existante

13

Client 1

Client 2

Client 3

Scheduler

Requête HTTP R1

Requête HTTP R3

Requête HTTP R2

Instances occupées

R2 R1

Requête HTTP R3

File d’attente

Instances fraîchesUne application non optimisée -> temps d’attente important-> UX dégradée + argent dépensé dans le CPU

Page 14: Formation Google App Engine

GAE: Dashboard d’administration14

Page 15: Formation Google App Engine

Code Lab N1

Pré-requis: • Eclipse JEE Edition• JDK 6• SDK GAE pour Java• Version JEE de Eclipse• Google plugin pour Eclipse• Un compte Gmail• Un téléphone mobile

Objectifs:• Créer votre première application sur GAE• Déploiement en Live• Comprendre le cycle de développement sur GAE• Se familiariser avec la console d’administration

• Instructions dans le fichier lab1.pdf

15

Page 16: Formation Google App Engine

Deuxième partie

GAE: Services

16

Page 17: Formation Google App Engine

Services dans GAE

• GAE offre une variété de services qui augmentent la productivité• La plupart de ces services respectent les standards Java

17

Page 18: Formation Google App Engine

Services Clés18

Page 19: Formation Google App Engine

String key = ‘email’;   User user =null;

    // Using the synchronous cache    MemcacheService syncCache = MemcacheServiceFactory.getMemcacheService();     user = (User) syncCache.get(key); // read from cache    if (user == null) {      // get user from other source (Date Store)      // ........      syncCache.put(key, user, Expiration.byDeltaSeconds(60)); // populate cache    }

MemCache

• Cache distribué pour stocker les données• Deux modes d’écriture: synchrone et asynchrone• Mémoire volatile• Taille maximale de 1Mb par objet stocké

19

Bonne pratique: 1- Memcache est un service à utiliser sans modération afin de soulager le DateStore2- Faire des insertions en Batch -> cache.putAll(values)

Page 20: Formation Google App Engine

Files d’attente: Task Queue

• Effectuer un traitement en tâche de fond en dehors des requêtes des utilisateurs

• Organiser le travail en petites unités discrètes appelées tâches• Ces tâches sont mises dans une ou plusieurs files d'attente• Elles sont exécutées lorsque les ressources système le permettent

20

Caractéristiques Push Queue Pull Queue

Scalabilité Automatique par GAE A votre charge(workers backend)

Gestion des tâches Automatique A votre charge(suppression,…etc)

Accès par les tiers non Oui (Rest API)

Quota: Taille maxi / tâcheNombre max de queues activesTaux d’exécution maxi

100 Kb10 Free, 100 app payante500/sec/queue

1 Mb10 Free, 100 app payantePersonnalisable

Page 21: Formation Google App Engine

<queue-entries>  <queue>    <name>queue_name</name>    <rate>1/s</rate> <bucket-size>40</bucket-size>    <max-concurrent-requests>10</max-concurrent-requests>    <retry-parameters>      <task-retry-limit>7</task-retry-limit>      <task-age-limit>2h</task-age-limit>    </retry-parameters>  </queue>

Push Queues en pratique

• WEB-INF/queue.xml

21

import com.google.appengine.api.taskqueue.Queue;import com.google.appengine.api.taskqueue.QueueFactory;import static com.google.appengine.api.taskqueue.TaskOptions.Builder.*;

// ...    Queue queue = QueueFactory.getQueue("queue_name");    queue.add(withUrl("/worker").param("key", key));

Page 22: Formation Google App Engine

try {            URL url = new URL("http://www.example.com/atom.xml");            BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));            String line;            while ((line = reader.readLine()) != null) {                // ...            }            reader.close();

        } catch (Exception e) {            // ...        }

Url Fetch

• API pour communiquer avec d’autres applications ou accéder à d’autres ressources sur le Web

• Support du protocole HTTP (POST, GET, PUT,…)• Appels en synchrone et asynchrone

22

Restriction Quantité

taille d'une requête 1 Mo

taille d'une réponse 1 Mo

Pour savoir plus sur les quotas du service Url Fetchhttps://developers.google.com/appengine/docs/quotas#UrlFetch

Page 23: Formation Google App Engine

Blobstore

• Service capable de servir et recevoir des fichiers importants souvent via un formulaire d’upload

• Possibilité d’écrire dynamiquement des blobs• Intégration native avec l’API de conversion

23

BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();

public void doGet(HttpServletRequest req, HttpServletResponse res)    throws IOException {        BlobKey blobKey = new BlobKey(req.getParameter("blob-key")); // servir un fichier blob        blobstoreService.serve(blobKey, res);    }}

Restriction Quantité

Taille d'un Blob 32 Mo

Taille totale des blobs 5 Gb

Page 24: Formation Google App Engine

Properties props = new Properties();        Session session = Session.getDefaultInstance(props, null);        String msgBody = "...";            Message msg = new MimeMessage(session);            msg.setFrom(new InternetAddress("[email protected]", "Example.com Admin"));            msg.addRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]", "Mr. User"));            msg.setSubject("Your Example.com account has been activated");            msg.setText(msgBody);            Transport.send(msg);

Mail API

• Envoyer des email au nom de l’administrateur• Recevoir des emails dans l’application

24

Ressource Daily Limit Maximum Rate

Mail API Calls 100 calls 32 calls/minute

Messages Sent 100 messages 8 messages/minute

Admins Emailed 5,000 mails 24 mails/minute

Message Body Data Sent 60 MB 340 KB/minute

Attachments Sent 2,000 attachments 8 attachments/minute

Attachment Data Sent 100 MB 10 MB/minute

Page 25: Formation Google App Engine

<cronentries>  <cron>    <url>/recache</url>    <description>Repopulate the cache every 2 minutes</description>    <schedule>every 2 minutes</schedule>  </cron>  <cron>    <url>/weeklyreport</url>    <description>Mail out a weekly report</description>    <schedule>every monday 08:30</schedule>    <timezone>America/New_York</timezone>  </cron></cronentries>

Tâches planifiées (cron)

• Configurer des tâches planifiées qui s'exécutent à des heures définies ou à intervalles réguliers

• Très utile pour l’envoi des rapports, rafraichir des éléments dans le cache ..etc

25

Page 26: Formation Google App Engine

AppStats

• Maitriser l’utilisation des Services GAE• Optimiser les requêtes internes et externes

26

Page 27: Formation Google App Engine

Code Lab N2

Objectifs:• Initiation à l’utilisation des services clés de GAE• Savoir optimiser son code grâce à AppStats• Maitriser le temps d’exécution des requêtes (Backend performance)

• Instructions dans le fichier lab2.pdf

27

Page 28: Formation Google App Engine

Troisième partie

GAE: Persistance des données

28

Page 29: Formation Google App Engine

Options offertes

• App Engine DataStore• Google Cloud SQL• Google Cloud Storage• Garder vos données chez vous!

29

Page 30: Formation Google App Engine

App Engine Datastore

• Base de données non relationnelle de type clé – valeur basée sur BigTable

• Architecture distribuée• Scalabilité et réplication automatique• Beaucoup de différences avec les RDBMS traditionnels:

– Pas de schéma– Requêtes pré-indexées– Pas de d’opération Join– Pas de fonctions d’agrégation

• Accès via:– Standards Java: JDO/JPA, Hibernate– Low-level API– Librairies tierces: Objectify, Twig,..

30

Page 31: Formation Google App Engine

GAE Datastore: vocabulaire

• Entity: Objet contenant des données stockées dans le datastore– Deux entités du même type peuvent avoir des propriétés différentes– Une application GAE ne peut accéder qu’aux entités qu’elle a créé

• Key: Propriété qui identifie une entité dans le datastore– Une entité est identifiable par trois propriétés:

• Kind: type de l’entité (nom de la classe)• Id: identifiant de l’entité• Parent: Option pour définir l’emplacement de stockage d’une entité dans le

datastore– Une entité sans parent est dite entité root

• Entity group: Une entité, ses parents et ses fils (ancestor path) appartiennent à la même entity group

• Index: Propriété qui permet d’exécuter une requête sur le datastore• Transaction: Une opération, ou un ensemble d’opérations

atomiques -> indivisibles

31

Page 32: Formation Google App Engine

Gestion d’accès32

Datastore 1App 1

App 2

App 3

Remote API

Accès direct

Accès direct

Version1.0.6

Version1.0

VersionTest

Page 33: Formation Google App Engine

Autres limitations

• On ne peut pas exécuter une requête sur une propriété non indexée• Un index met du temps pour être disponible (mis à jour)• Le parent d’une entité est permanent• Les requêtes sont limitées à un seul groupe d’entité (Entity group)• Un seul filtre d’inégalité est autorisé

33

Resource Free Default Daily LimitBilling Enabled Default Limit

Stored Data 1 GB Note: Not a daily limit but a total limit.

1 GB free; no maximum

Number of Indexes 200 Note: Not a daily limit but a total limit.

200

Write Operations 50,000 Unlimited

Read Operations 50,000 Unlimited

Maximum entity size 1 Mb 1Mb

Maximum transaction size 10 Mb 10Mb

Page 34: Formation Google App Engine

Objectify

• Bibliothèque qui vous permet de persister des objets Java en toute simplicité

• Forte abstraction des API du Datastore• Quatre opérations basiques GET, PUT, DELETE, QUERY• Annotations Java• Système de cache qui se base sur le service MemCache & sessions

34

public class Car{    @Id Long id;    @Unindexed String prop;    int color;    @Transient String doNotPersist;

    private Car() {} // mandatory no-arg constructor        public Car(String prop, int color) {        this. prop = prop;        this.color = color;    }}

Page 35: Formation Google App Engine

Objectify en pratique35

// Vous devez enregistrer vos entités ClassObjectifyService.register(Car.class);ObjectifyService.register(Motorcycle.class);

Objectify ofy = ObjectifyService.begin();

// Simple createCar porsche = new Car("2FAST", "red");ofy.put(porsche);assert porsche.id != null;    // id was autogenerated

// Get it backCar fetched1 = ofy.get(new Key<Car>(Car.class, porsche.id));Car fetched2 = ofy.get(Car.class, porsche.id);    // equivalent, more convenientassert areEqual(porsche, fetched1, fetched2);

// Change some data and write itporsche.color = "blue";ofy.put(porsche);

// Delete itofy.delete(porsche);

Page 36: Formation Google App Engine

Objectify: opérations en batch36

Objectify ofy = ObjectifyService.begin();

// CreateCar porsche = new Car("2FAST", "red");Car unimog = new Car("2SLOW", "green");Car tesla = new Car("2NEW", "blue");ofy.put(tesla, unimog, porsche);    //varargs; Car[] and Iterable<Car> also work

// More convenient shorthand, note the return typeMap<Long, Car> fetched = ofy.get(Car.class, new Long[] { porsche.id, unimog.id, tesla.id });

// Delete the dataofy.delete(fetched.values());

// You can delete by key without loading the objectsofy.delete(    new Key<Car>(Car.class, porsche.id),    new Key<Car>(Car.class, unimog.id),    new Key<Car>(Car.class, tesla.id));

Page 37: Formation Google App Engine

Objectify: les requêtes37

Objectify ofy = ObjectifyService.begin();

Car car = ofy.query(Car.class).filter("prop", "123456789").get();

// The Query itself is IterableQuery<Car> q = ofy.query(Car.class).filter("prop >", "123456789").order("-prop");for (Car car: q) {    System.out.println(car.toString());}

// You can query for just keys, which will return Key objects much more efficiently than fetching whole objectsIterable<Key<Car>> allKeys = ofy.query(Car.class).fetchKeys();

// Useful for deleting itemsofy.delete(allKeys);

Page 38: Formation Google App Engine

Objectify: Polymorphisme

• L’entité root doit porter l’annotation @Entity• Les classes polymorphes doivent porter l’annotation @Subclass• Une modification dans la hiérarchie des classes nécessite une mise

à jour des index

38

@Entitypublic class Animal {    @Id Long id;    String name;}        @Subclasspublic class Mammal extends Animal {    boolean longHair;}        @Subclasspublic class Cat extends Mammal {    boolean hypoallergenic;}

Page 39: Formation Google App Engine

Objectify: Polymorphisme - suite39

Objectify ofy = ObjectifyService.begin();

Animal annie = new Animal();annie.name = "Annie";ofy.put(annie);

Mammal mam = new Mammal();mam.name = "Mam";m.longHair = true;ofy.put(mam);

Cat minou= new Cat(); minou.name = "Minou"; minou.longHair = true; ofy.put(minou);

// This will return the CatAnimal fetched = ofy.get(Animal.class, minou.id);

// This query will produce three objects, the Animal, Mammal, and CatQuery<Animal> all = ofy.query(Animal.class);

// This query will produce the Mammal and CatQuery<Mammal> mammals = ofy.query(Mammal.class);

Page 40: Formation Google App Engine

Les transactions

• Une transaction peut manipuler des données de différents Entity Group

• 5 Entity Group maxi

40

Objectify ofy = ObjectifyService.beginTransaction();  // instead of begin()try{    ClubMembers cm = ofy.get(ClubMembers.class, "k123");    cm.incrementByOne();    ofy.put(cm);

    ofy.getTxn().commit();}finally{    if (ofy.getTxn().isActive())        ofy.getTxn().rollback();}

Page 41: Formation Google App Engine

Les relations entre le objets

• Relation Parent– Les classes Person et Car appartiennent au même Entity Group– Modifier le owner créera une nouvelle entité mais ne supprimera pas l’ancienne!– La relation parent est permanente

41

public class Person {    @Id Long id;    String name;}

public class Car {    @Id Long id;    @Parent Key<Person> owner;    String color;}

Objectify ofy = ObjectifyService.begin();

Key<Person> owner = new Key<Person>(Person.class, somePersonId);Car someCar = ofy.get(new Key<Car>(owner, Car.class, someCarId));

Page 42: Formation Google App Engine

Relation Single-Value

• Dans une relation single-value, une clé une propriété comme les autres propriétés de l’entité

- One to one - Many to One

42

public class Person {    @Id String name;    Key<Person> significantOther;}Objectify ofy = ObjectifyService.begin();Person bob = ofy.get(Person, "bob");Person bobswife = ofy.get(bob.significantOther);

public class Employee{    @Id String name;    Key<Employee> manager;}

Objectify ofy = ObjectifyService.begin();Employee bob = ofy.get(Employee.class, "bob");Employee fred = ofy.get(bob.manager);

Iterable<Employee> subordinates = ofy.query(Employee.class).filter("manager", fred);

Page 43: Formation Google App Engine

Relation Multi-value

• Le Datastore peut aussi persister des collections et des tableaux• 5000 sous entités au maximum• Chaque get() ou put() chargera/mettra à jour les clés de toutes les

sous entités (performance)

43

public class Employee{    @Id String name;    Key<Employee>[] subordinates;}

Objectify ofy = ObjectifyService.begin();

// should contain FredIterable<Employee> managers = ofy.query(Employee.class).filter("subordinates", bob);

Page 44: Formation Google App Engine

Statistiques sur vos données44

Accès dynamique en java: https://developers.google.com/appengine/docs/java/datastore/stats

Page 45: Formation Google App Engine

Code Lab N3

Objectifs:

• Initiation à la persistance des données dans le Datastore de GAE grâce à la bibliothèque Objectify

• Inspecter les interactions avec le Datastore grâce au service AppStats

• Instructions dans le fichier lab3.pdf

45

Page 46: Formation Google App Engine

Quatrième partie

Webservices Rest

46

Page 47: Formation Google App Engine

Restlet

• Framework Java pour développer des API REST réutilisables sur d’autres plateformes (Android, GWT,…)

• Support de plusieurs représentations (XML,JSON,JAXB,…)• Fonctionnalités avancées pour le rooting et la sécurité• Négociation de contenu

47

Page 48: Formation Google App Engine

Exemple d’une application Restlet48

Page 49: Formation Google App Engine

Webservices Rest - Démo

49

Page 50: Formation Google App Engine

Code Lab N4

Objectifs:• Initiation aux développement des API REST avec le framework Restlet

• Instructions dans le fichier lab4.pdf

50

Page 51: Formation Google App Engine

Merci de votre attentionQuestions & Réponses

RHANIZAR Abdelhakim [email protected] @a_rhanizar