Publicité

Devoxx: Tribulation d'un développeur sur le Cloud

Technical Evangelist at MapR à MapR Technologies
19 Apr 2012
Publicité

Contenu connexe

Similaire à Devoxx: Tribulation d'un développeur sur le Cloud(20)

Publicité
Publicité

Devoxx: Tribulation d'un développeur sur le Cloud

  1. Tribulations d'un développeur Java dans le Cloud Tugdual Grall @tgrall 1
  2. Ce que vous allez apprendre • Retour d’experience d’un developpeur du “Dimanche” • Comprendre “mes” choix • Difficultés Surprises du Cloud 2
  3. About me : “Tug” • CTO chez eXo depuis 2008 • Développeur, Product Manager chez Oracle • Co fondateur du NantesJUG • @tgrall sur Twitter & RunKeeper • Triathlete • Développeur de resultri.com 3
  4. Agenda • Le Cloud, Pourquoi ? Comment ? • Les surprises Bonnes et Mauvaises • Et Alors ? 4
  5. Le cloud, pourquoi? • Besoins fonctionnels : • Analyser les résultats de courses :Triathlons ou autres • Partager ces résultats simplement : réseaux sociaux • Besoins techniques : • Apprendre à développer pour le cloud • Pas de gestion système, ressources disponibles 5
  6. 6
  7. Choisir une plateforme • Aout 2011, avant mon départ en vacances • Support du mode déconnecté • Java & NoSQL • Documentée et “Connue” • Gratuite • Disponible sur Mac OS X sans “hack” 7
  8. Choisir une plateforme • Aout 2011, avant mon départ en vacances • Support du mode déconnecté • Java & NoSQL • Documentée et “Connue” • Gratuite • Disponible sur Mac OS X sans “hack” 7
  9. Google AppEngine • Google PaaS • Languages : Java, Python and Go • Base de données : BigTable (NoSQL) & CloudSQL (MySQL) • Accès simplifié aux API et Services Google • Google Cloud Storage, Analytics, Google Apps, Maps... 8
  10. Resultri en quelques mots • Pour les Geeks • Pour les Sportifs • Pure Servlet/JSP • 33 courses • REST avec JAX-RS (Jersey) • 46 754 résultats individuels • Twitter Boostrap • 3500 visiteurs uniques • 11 300 pages vues 9
  11. Traitement des données 10
  12. Accès aux données? • Ma premiere réelle experience du monde NoSQL • Mon passé (passif?) : 9 années d’Oracle, ... très SQL (JPA,Toplink, BC4J !) • API : JPA, JDO, Datastore API ou autre (Objectify) ? 11
  13. Accès aux données? • Mon choix : JDO & Datastore API • Limité aux API Google (documenté dans le SDK) • JDO : car la doc était la plus complète • Datastore : est venu ensuite pour la simplicité 12
  14. Resultri: Les Données Sites “résultats” HTML, TXT, CSV, XML 13
  15. Resultri: Les Données Sites “résultats” Traitements en local HTML, TXT, CSV, XML Utilisation du GAE Dev Server Export CSV 13
  16. Resultri: Les Données Sites “résultats” Traitements en local Import GAE HTML, TXT, CSV, XML Utilisation du GAE Dev Server Utilisation des outils GAE Export CSV Import CSV 13
  17. Dev to “Cloud” 1/2 1: DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); • 2: ... Une fois les données 3: Map<String, Object> propertiesMap = result.getProperties(); 4: properties = (String[]) propertiesMap.keySet()...; 5: ... 6: 7: Query q = new Query("TriathlonResult"); q.addFilter("raceURI", Query.FilterOperator.EQUAL,race); importées en local 8: PreparedQuery pq = datastore.prepare(q); • 9: for (Entity result : pq.asIterable()) { 10: 11: 12: ! for (int i = 0; i < properties.length; i++) { Object o = result.getProperty(properties[i]); Création d’un Fichier CSV 13: String printValue = null; • 14: if (o != null) { 15: 16: ! ! if (o instanceof java.util.Date) { ! SimpleDateFormat formatter = new SimpleDateFormat("yyy ... H:mm:ss") ; Utilisation des API Datastore 17: ! ! Date date = (Date) o; • 18: ! ! printValue = formatter.format(date); 19: 20: ! } } else if ... { ...!} Trop “couteux” à faire sur le Cloud 21: out.print((printValue == null)?"":printValue); 22: out.print(","); 23: ! } 24: ... 14
  18. Dev to “Cloud” 2/2 appcfg.py upload_data --config_file=config.yml --filename=ironman-south-africa.csv --url=http://dev-result-db.appspot.com/remote_api --application=dev-result-db --kind=TriathlonResult Uploading data records. [INFO ] Logging to bulkloader-log-20120416.155812 [INFO ] Throttling transfers: • Création des entités par CLI [INFO ] Bandwidth: 250000 bytes/second [INFO ] HTTP connections: 8/second [INFO ] Entities inserted/fetched/modified: 20/second [INFO ] Batch Size: 10 • Très rapide • [INFO ] Opening database: bulkloader-progress-20120416.155812.sql3 [INFO ] Connecting to dev-result-db.appspot.com/remote_api Please enter login credentials for dev-result-db.appspot.com Import des données “formatées” Email: tugdual@gmail.com Password for tugdual@gmail.com: [INFO ] Starting import; maximum 10 entities per post ................................................................. [INFO ] 1552 entities total, 0 previously transferred [INFO ] 1552 entities (7016782 bytes) transferred in 60.4 seconds [INFO ] All entities successfully transferre 15
  19. Recherche Full Text • Beta privée en Octobre... • Solution “Resultri” • Utilisation de Cloud SQL 16
  20. Recherche Full Text • Beta privée en Octobre... • Solution “Resultri” • Utilisation de Cloud SQL First & Last Names BigTable CloudSQL 16
  21. Accès aux données • Attention aux quotas ! 17
  22. Accès aux données • Utilisation de Memcache • Cache disponible dans GAE • Gestion du cache par le biais de l’API JCache (JSR-107) ou API Google • Dans Resultri: • Tout Entity est automatiquement cachée 18
  23. Memcache 19
  24. Les surprises .... 20
  25. Création de données 1: log.info(" -- Start -- "); 2: DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); 3: Entity employee = new Entity("Employee"); 4: employee.setProperty("firstName", "Nicolas"); 5: employee.setProperty("lastName", "Martignole"); 6: Date hireDate = new Date(); 7: employee.setProperty("hireDate", hireDate); 8: employee.setProperty("attendedHrTraining", true); 9: datastore.put(employee); 10: employee = new Entity("Employee"); 11: employee.setProperty("firstName", "Antonio"); 12: employee.setProperty("lastName", "Goncalvez"); 13: hireDate = new Date(); 14: employee.setProperty("hireDate", hireDate); 15: employee.setProperty("attendedHrTraining", true); 16: datastore.put(employee); 17: Query q = new Query("Employee"); 18: PreparedQuery pq = datastore.prepare(q); 19: for (Entity emp : pq.asIterable()) { 20: ! log.info(emp.getProperty("firstName") + " "+ emp.getProperty("lastName" ); 21: } 22: log.info(" -- End -- "); 21
  26. Création de données 1: log.info(" -- Start -- "); 2: DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); 3: Entity employee = new Entity("Employee"); 4: employee.setProperty("firstName", "Nicolas"); 5: employee.setProperty("lastName", "Martignole"); 6: Date hireDate = new Date(); 1: Apr 16, 2012 4:22:25 "hireDate", hireDate); 7: employee.setProperty( PM com....Servlet doGet 2: INFO: -- setProperty("attendedHrTraining", true); 8: employee. Start -- 3: Apr 16, 2012 4:22:25 PM com....Servlet doGet 9: datastore.put(employee); 4: INFO: Nicolas Martignole 10: employee = new Entity("Employee"); 5: Apr 16, 2012 4:22:25 "firstName", "Antonio"); 11: employee.setProperty( PM com....Servlet doGet 6: INFO: -- setProperty("lastName", "Goncalvez"); 12: employee. End -- 7: Apr 16, 2012 4:Date(); com.......$PersistDatastore persist 13: hireDate = new 22:34 PM 8: INFO: Time to persist"hireDate",: hireDate); 14: employee.setProperty( datastore 4 ms 15: employee.setProperty("attendedHrTraining", true); 16: datastore.put(employee); 17: Query q = new Query("Employee"); 18: PreparedQuery pq = datastore.prepare(q); 20: ! Mais où est parti Antonio???? 19: for (Entity emp : pq.asIterable()) { log.info(emp.getProperty("firstName") + " "+ emp.getProperty("lastName" ); 21: } 22: log.info(" -- End -- "); 21
  27. Datastore : Queries 1: Query q = new Query("Employee"); 2: q.addSort("lastName"); 3: q.addSort("firstName"); 4: PreparedQuery pq = datastore.prepare(q); 5: for (Entity emp : pq.asIterable()) { 6: o.println(emp.getProperty("lastName") +" "+ emp.getProperty("firstName") ); 7: } 22
  28. Datastore : Queries 1: Doe John 2: Goncalvez Antonio 1: Query q = new Query("Employee"); 3: Grall Briac 2: q.addSort("lastName"); 4: Grall Corentin 3: q.addSort("firstName"); 5: Grall Malo 4: PreparedQuery pq = datastore.prepare(q); 6: Grall Nolwenn 5: for (Entity emp : pq.asIterable()) { 7: Grall Tug 8: Grall Virginie 6: o.println(emp.getProperty("lastName") +" "+ emp.getProperty("firstName") ); 9: Martignole Nicolas 7: } 10: Tabarly Eric 22
  29. Datastore : Queries 1: Query q = new Query("Employee"); 2: q.addFilter("lastName", FilterOperator.EQUAL , "Grall"); 3: q.addSort("lastName"); 4: q.addSort("firstName"); 5: PreparedQuery pq = datastore.prepare(q); 6: for (Entity emp : pq.asIterable()) { 7: o.println(emp.getProperty("lastName") + " "+ emp.getProperty("firstName") ); 8: } 23
  30. Datastore : Queries 1: Query q = new Query("Employee"); 2: q.addFilter("lastName", FilterOperator.EQUAL , "Grall"); 1: Grall Briac 3: q.addSort("lastName"); 2: Grall Corentin 4: q.addSort("firstName"); 3: Grall Malo 5: PreparedQuery pq = datastore.prepare(q); 4: Grall Nolwenn 6: for (Entity emp : pq.asIterable()) { 5: Grall Tug 6: Grall Virginie 7: o.println(emp.getProperty("lastName") + " "+ emp.getProperty("firstName") ); 8: } 23
  31. Datastore : Queries 1: Query q = new Query("Employee"); 2: q.addFilter("lastName", FilterOperator.EQUAL , "Grall"); 3: q.addFilter("birthYear", FilterOperator.LESS_THAN_OR_EQUAL , 2000); 4: q.addSort("lastName"); 5: q.addSort("firstName"); 6: PreparedQuery pq = datastore.prepare(q); 7: for (Entity emp : pq.asIterable()) { 8: o.println(emp.getProperty("lastName") + " "+ emp.getProperty("firstName") ); 9: } 24
  32. Datastore : Queries 1: Query q = new Query("Employee"); 2: q.addFilter("lastName", FilterOperator.EQUAL , "Grall"); 3: q.addFilter("birthYear", FilterOperator.LESS_THAN_OR_EQUAL , 2000); 4: q.addSort("lastName"); ? 5: q.addSort("firstName"); 6: PreparedQuery pq = datastore.prepare(q); 7: for (Entity emp : pq.asIterable()) { 8: o.println(emp.getProperty("lastName") + " "+ emp.getProperty("firstName") ); 9: } 24
  33. Datastore : Queries 1: Query q = new Query("Employee"); 2: q.addFilter("lastName", FilterOperator.EQUAL , "Grall"); 3: q.addFilter("birthYear", FilterOperator.LESS_THAN_OR_EQUAL , 2000); 4: q.addSort("lastName"); java.lang.IllegalArgumentException: ? 5: q.addSort("firstName"); The first sort property must be the same as the property to which the inequality filter is applied. 6: PreparedQuery pq = datastore.prepareproperty is firstName but the inequality filter is on birthYear In your query the first sort (q); 7: for (Entity emp : pq.asIterable()) { 8: o.println(emp.getProperty("lastName") + " "+ emp.getProperty("firstName") ); 9: } 24
  34. Datastore : Queries 1: PersistenceManager pm = PMF.get().getPersistenceManager(); 2: Query q = pm.newQuery(Employee.class,"lastName=='Grall'&& firstName=='Malo'"); 3: List<Employee> results = (List<Employee>) q.execute(); ! 4: o.println(results); 25
  35. Datastore : Queries 1: PersistenceManager pm = PMF.get().getPersistenceManager(); 2: Query q = pm.newQuery(Employee.class,"lastName=='Grall'&& firstName=='Malo'"); 3: List<Employee> results = (List<Employee>) q.execute(); ! 1: Grall Malo 4: o.println(results); 25
  36. Datastore : Queries 1: PersistenceManager pm = PMF.get().getPersistenceManager(); 2: Query q = pm.newQuery(Employee.class,"lastName=='Grall'|| firstName=='Malo'"); 3: List<Employee> results = (List<Employee>) q.execute(); ! 4: o.println(results); 26
  37. Datastore : Queries 1: PersistenceManager pm = PMF.get().getPersistenceManager(); 2: Query q = pm.newQuery(Employee.class,"lastName=='Grall'|| firstName=='Malo'"); 3: 4: List<Employee> results = (List<Employee>) q.execute(); ! o.println(results); ? 26
  38. Datastore : Queries 1: PersistenceManager pm = PMF.get().getPersistenceManager(); org.datanucleus.store.appengine.query.DatastoreQuery$UnsupportedDatastoreFeatureException: 2: Problem = pm.newQuery(Employee.class,"lastName=='Grall'|| firstName=='Malo'"); Query q with query <SELECT FROM com.grallandco.model.Employee WHERE lastName=='Grall' || firstName=='Malo'>: 3: Or filters cannot be applied<Employee>) q.execute(); ! (found both lastName and firstName). List<Employee> results = (List to multiple properties 4: o.println(results); ? 26
  39. Manipulation des données • Les données ne sont pas toujours disponibles • High Data Replication (HDR) : surprenant pendant les tests • “Limitations” des requêtes (GQL) et JDO • Attentions aux index : sans index pas de “requetes” • Verifier la disponibilité des index • Utilisation de Memcache (must have! ) 27
  40. Autres services 28
  41. Task Queues • Service pour l’execution de taches en arrière plan • Possibilité d’inclure les taches dans un ordonnanceur (cron) • Resultri: • Synchronization (BigTable/CloudSQL) , Nettoyage des données 1: Queue queue = QueueFactory.getQueue("SynchappAppQueue"); 2: TaskOptions taskOptions = TaskOptions.Builder.withUrl("/worker/ProcessSynchronizeDataServlet") 3: .param("race-uri", "ironman-florida-2005") 4: .param("type", "syncDB") 5: .method(TaskOptions.Method.POST); 6: queue.add(taskOptions); 29
  42. Test en Local • Un version de Jetty avec le SDK Google AppEngine Simulation “Authentification Google” Console Developpeur 30
  43. Disponibilité des services 31
  44. Authentification Google • Utilisation de Google Account • Se base sur la sécurité JavaEE standard • Gestion des administrateurs par le biais de la console AppEngine <security-constraint> <web-resource-collection> <url-pattern>/admin/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>admin</role-name> </auth-constraint> </security-constraint> 32
  45. URL Fetch • Accès à des serveurs autres que AppEngine par HTTP/HTTPS • Utilisation de java.net.URL ou com.google.appengine.api.urlfetch.URLFetchService • Dans Resultri : utilisation du service de GeoCodage de Google Maps 1: URL url = new URL("http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address="+ address ); 33
  46. Accès aux API Google • Google offre de nombreux Services et API • Un seul compte => tous les services 34
  47. Resultri & Google • Les services que j’utilise pour Resultri • Google Apps : Gestion du nom de domaines, Mail, ... • CloudSQL : Recherche Full Text (MySQL) • Cloud Storage : Sauvegarde BigTable, Serveur de fichiers • Google Maps • Analytics, Adsense, Webmaster 35
  48. En production 36
  49. Gratuit ? • Oui mais.... • Avec des quotas • Les règles peuvent changer • Septembre : Google modifie ses tarifs 37
  50. Gratuit ? • Oui mais.... • Avec des quotas • Les règles peuvent changer • Septembre : Google modifie ses tarifs 37
  51. Exemple 38
  52. Exemple Import CSV 38
  53. Gestion du cout • En Fevrier : Augmentation du cout • Pas d’activité utilisateur, mais cout en augmentation 39
  54. Gestion du cout • En Fevrier : Augmentation du cout • Pas d’activité utilisateur, mais cout en augmentation • Une idée ? 39
  55. Merci Google! • Google Bots, et autres moteurs de recherche • Utilisation de Google Webmaster Tools • Mise en place d’un fichier robots.txt 40
  56. Merci Google! • Google Bots, et autres moteurs de recherche User-agent: Twiceler • Disallow: / Utilisation de Google Webmaster Tools User-agent: psbot Disallow: / • User-agent: * Mise en place d’un fichier robots.txt Disallow: /search Disallow: /races/*/compare Disallow: /rest Disallow: /races/*/*/position Disallow: /races/*/*/rank Disallow: /races/*/*/otherRaces Disallow: /races/*?page=-* 40
  57. Merci Google! • Google Bots, et autres moteurs de recherche User-agent: Twiceler • Disallow: / Utilisation de Google Webmaster Tools User-agent: psbot Disallow: / • User-agent: * Mise en place d’un fichier robots.txt Disallow: /search Disallow: /races/*/compare Disallow: /rest • Disallow: /races/*/*/position 243 784 URL bloquées sur Resultri Disallow: /races/*/*/rank Disallow: /races/*/*/otherRaces Disallow: /races/*?page=-* 40
  58. Console 41
  59. Console 41
  60. Console 41
  61. Conclusion 42
  62. Conclusion • AppEngine est-il le bon choix pour Resultri? • Pour l’instant trop couteux et “puissant” • Techniquement passionnant • Feuille de route • Gestion des utilisateurs : Facebook, Twitter, Google • Notifications • Version Mobile 43
  63. Conclusion • Techniquement : j’apprends beaucoup.... • Publication d’articles sur mon blog • NoSQL, CloudSQL, Memcache.... • Twitter Boostrap 2 and Google Maps • Google AppEngine Full Text Search with Cloud • Utilisation de Git SQL • Installing Memcached on Mac OS X and using it in • Twitter Bootstrap, Less Java • JAX-RS: Jersey and JSON single element arrays • Create and Deploy a JAX-RS REST service on Google App Engine • .... 44
  64. Questions? 45
  65. Tribulations d'un développeur Java dans le Cloud Tugdual Grall @tgrall 46

Notes de l'éditeur

  1. \n
  2. Bas&amp;#xE9; sur MON retour d&amp;#x2019;experience: je ne suis pas un specialiste de GAE !\nJuste un developpement pour le fun\nJe passe tres peu de temps sur cette appli (de moins en moins...)\n\nExplication de mes choix et des &amp;#x201C;problemes&amp;#x201D; rencontr&amp;#xE9;s\n
  3. Chez eXo, Oracle... developpement Java, JavaEE, SOA, ...\nCo Fondateur en 2008 du NantesJUG\nTwitter.... et comme nous allons parler sport: runkeeper\n\nQd je ne te travaille pas, ou je ne m&amp;#x2019;occupe pas de mes enfants...\n - je m;entraine ou coure.... et quelque fois je code\n - notamment dans le train (2h en gros)\n
  4. Voici la structure de la presentation...\n- mes choix et besoins\n- les bonnes surprises, decouvertes (et les moins bonnes) du cloud (GAE)\n- conclusion,,,\n
  5. L&amp;#x2019;id&amp;#xE9;e de ce site est parti de 2 besoins:\n 1- besoin &amp;#x201C;fonctionnel&amp;#x201D; analyser les resultats, suivre les copains et mes evolutions\n 2- besoin &amp;#x201C;technique&amp;#x201D; : une application plus pouss&amp;#xE9;e qu&amp;#x2019;un simple helloworld pour plonger un peu plus dans le cloud (ou sauter)\n
  6. \nPetite demo...\n\nVoici quelques ecrans de mon application.\nJe ne vais pas rentrer dans les details fonctionnels pour le moment....\n\n
  7. Voici mes &amp;#x201C;contraintes techniques&amp;#x201D;.\nLe point le plus important :\n - un projet perso developp&amp;#xE9; en vacances.\n - Commence dans un club de vacances en italie : Pizza &amp; Java\n\nBase sur les crit&amp;#xE8;res precedents j&amp;#x2019;ai choisi GAE.\n- Heroku, RH OpenShift ne supportaient pas encore Java\n- MicroCloud pas encore lanc&amp;#xE9;\n- EC2 trop cher/complique (au sens systeme, je veux une PaaS et non pas IaaS)\n\n\n
  8. GAE repond bien a tous ces criteres &amp;#x201C;techniques&amp;#x201D;\nLes autres services Google m&amp;#x2019;apparaissaient egalement tres interessant a integrer...G+ aussi :)\n
  9. Pourquoi Pure JSP/Servlet ? \n - pourquoi pas ? manque de competence sur les nouveaux fwk de ma part (JSF, Struts, OK,, mais quel int&amp;#xE9;r&amp;#xEA;t ?)\n - je ne voulais pas partir sur une solution Grails, Gaelyk, Play!, car je veux vraiment me concentrer sur GAE lui meme.\n\nLa migraton twitter 1.x - 2... un peu lourde non ?\n
  10. \n
  11. Le choix de la technologie &amp;#x201C;web&amp;#x201D; etait simple pour moi: JSP/JSTL/Servlet/TwitterBS... avec JQuery et autres extensions.\nRestait donc le choix de la persistence.... en utilisant le NoSQL (qui etait en aout la seule base de don&amp;#xE9;e disponible)\n\ndonc....\n
  12. Je me suis orient&amp;#xE9; sur JDO et ... puis datastore.\nIl est clair que comme tout le reste de l&amp;#x2019;application les choix sont discutables... mais pour moi la seule partie vraiment importante de mon application est: la base de donn&amp;#xE9;e. (les donn&amp;#xE9;es &amp;#x201C;traitees&amp;#x201D;)\nOn peut considerer le reste comme jetable, si par la suite il faut que je refactorise certaine parties no pb...\nMon modele object est tres simple, seule le &amp;#x201C;volume&amp;#x201D; entre guillement pourrait etre important dans le future.\n\nDonc JDO: pour la doc, et le cote ORM (voir suite) et Datastore pour la simplicit&amp;#xE9;/flexibilit&amp;#xE9;\n
  13. Les donn&amp;#xE9;es sont captur&amp;#xE9;es sur des sites publics\n\n+ Import&amp;#xE9;es/transform&amp;#xE9;s en local sur le serveur de dev (Pure GAE)\n\n+ puis export&amp;#xE9; dans l&amp;#x2019;instance GAE avec l&amp;#x2019;outil suivant\n\n
  14. Les donn&amp;#xE9;es sont captur&amp;#xE9;es sur des sites publics\n\n+ Import&amp;#xE9;es/transform&amp;#xE9;s en local sur le serveur de dev (Pure GAE)\n\n+ puis export&amp;#xE9; dans l&amp;#x2019;instance GAE avec l&amp;#x2019;outil suivant\n\n
  15. Utilisation de la Datastore API pour &amp;#x201C;sortir&amp;#x201D; les donn&amp;#xE9;es de la base de dev... et la pousser vers le serveur de prod.\n
  16. Cet outil m&amp;#x2019;est tres utile pour importer les donn&amp;#xE9;es...\nIl est aussi utilisable pour exporter les entites depuis le serveur de prod \nIl est possible de formatter, et transformer les objets par ces scripts (python)\nNotamme export/import: csv, xml, ...\n
  17. Etonnemment, GAE ne support pas encore une recherche full text. \nbesoin simple : Rechercher les athletes par leur nom.\n\nPlusieurs approche possible aujourd&amp;#x2019;hui, elastic search, lucene in GAE : MAIS COMPLEX...\n\nJ ai donc choisi pour m&amp;#x2019;amuser et pour repondre au besoin d&amp;#x2019;utiliser CloudSQL (mySQL dans le cloud)\n
  18. Une fois le systeme en production, avec un gros nombre de data:\n - on voit rapidement le nombre de call aux API monter (meme en read only)...\n - 50 000 requetes en free... getPropety() == 1 call\n
  19. La gestion du cache dans mon application est relativement simple:\n- l&amp;#x2019;eviction est geree automatiquement par memcache (cela dit il est possible de pauser un timer sur le cache)\nAdministration du cache de facon globale dans Resultri:\n - &amp;#x201C;je vide certains caches&amp;#x201D; en fonction de mes operations (par exemple ajout d&amp;#x2019;une course, je vide le cache &amp;#x201C;courses&amp;#x201D; lors de la publication)\n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. je n&amp;#x2019;ai pas encore tester les &amp;#x201C;limites&amp;#x201D;\nMeilleure gestion des ressources\n
  33. Une bonne surprise:\n- support de l&amp;#x2019;authentification Google Account dans le serveur de test (avec support du role admin)\n- Console de dev, pour visualiser/administrer les entit&amp;#xE9;s, queues, ...\n
  34. Une fonctionnalit&amp;#xE9; que je trouve tres interessante:\n - la capacit&amp;#xE9; a tester avec les &amp;#x201C;services cloud&amp;#x201D; no disponible avec plusieurs etats....\n\nJe n&amp;#x2019;ai pas encore vraiment eu besoin d&amp;#x2019;utiliser cette fonctionnalit&amp;#xE9; mais vraiment &amp;#x201C;look nice&amp;#x201D;\n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. Sur cette petite animation vous pouvez voir qu&amp;#x2019;en utilisant l&amp;#x2019;outil APPCFG pour importer mes enregistrement (la moitie d&amp;#x2019;un ironman)\nj&amp;#x2019;explose le quota des Datastore write ...\nPour l&amp;#x2019;anedocte, ce matin j&amp;#x2019;ai fait le menage dans mes entities (suppression des enregistrement &amp;#x201C;session&amp;#x201D;) et cela a exploser mon budget (limit&amp;#xE9; a $1 par jour :( 0.39 front ent / 0.66 en ecriture ... je n&amp;#x2019;ai pas trop verifi&amp;#xE9; la source exacte du probleme )\n
  42. Que se passe-t-il ici?\nsur les images:\n - activite nulle...\n - prix eleve\n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. J&amp;#x2019;ai bcp appris, mais il me reste encore pas mal de chose a tester/faire:\n - optimisation des donn&amp;#xE9;es (volume, indexes, ..)\n - utlisation des services XMPP, mail. &amp;#x201C;pour voir&amp;#x201D;\n - utiliser les &amp;#x201C;versions&amp;#x201D; d&amp;#x2019;applications, et lesoutils de &amp;#x201C;mise a jour des donn&amp;#xE9;es)\n - FullText Search\n - MapReduce\n
  50. \n
  51. \n
Publicité