Daten speichern in Google App Engines Datastore

Die Google App Engine (GAE) ist eine freie Hosting-Plattform auf der Java Web-Applikationen deployt werden können. Google bietet für die GAP eine Reihe von Diensten an, etwa zur Datenspeicherung, Mail-Versand/-Empfang, Messaging und mehr. Wer sich für die GAE entscheidet und Daten speichern möchte, dem steht quasi unendliche Speicherkapazität zur Verfügung. Google speichert die Daten in einer Cloud, der Google BigTable (http://en.wikipedia.org/wiki/BigTable). Sie ist im Wesentlichen ein riesiger verteilter Assoziativspeicher.

Der Datestore – so wird die Datenspeicher für die Google App Engine genannt – speichert Entities. Eine Entity hat einen Typ (Entity-Kind genannt) und eine Menge von Schlüssel/Werte-Paaren. Eine konkrete Entity für eine Person könnte etwa die Schlüssel-Wert-Menge { name = „Chris“, age = 36 } speichern. Die Entities sind nicht mit klassischen Tabellenzeilen von relationalen Datenbanken zu vergleichen, das sie schemalos sind: Es gibt also keine Spalten mit festen Datentypen. Es können also beliebig viele „Spalten“ für gewisse Entities hinzukommen. Eine Person in der Datastore kann wie im ersten Beispiel Name und Alter speichern, eine andere Person Name und Schuhgröße. Die Anzahl Schlüssel ist wirklich beliebig; eine Tatsache die vom relationalen Design totales Umdenken erfordert.

Zum Zugriff auf den Datastore steht auf unterster Schicht eine Low-Level API (https://developers.google.com/appengine/docs/java/javadoc/com/google/appengine/api/datastore/package-summary). Diese API bietet grundlegende CRUD-Operationen und ist mit 10 Interfaces und etwas mehr als 50 Klassen leicht verständlich und übersichtlich. Wenn eine Person gespeichert werden soll, sieht das so aus:

Entity chris = new Entity( "Person" );
chris.setProperty("name", "chris");
chris.setProperty("age", 20 );
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(chris);

Jede Entity ist durch einen Schlüssel gekennzeichnet. Nach dem Speichern einer Entity lässt sich dieser Schlüssel über getKey() erfragen. Ist der Schlüssel bekannt, kann eine Anfrage an den Datastore gemacht werden.

Key key = chris.getKey();
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Entity e = datastore.get( key );
Long age = (Long) alice.getProperty("age");

Die Anfragen werden über den Entity-Typ gestellt, der in Key steckt. Alle Entities haben einen Entity-Kind und die Suche auf dem Datastore ist immer mit diesem Entity-Kind verbunden.

Der Datastore bietet eine hohe Lese- und Anfrage-Geschwindigkeit ist aber nicht unbedingt komfortablen.

https://developers.google.com/appengine/docs/java/datastore/?hl=de gibt auch auf Deutsch ein paar Hinweise. Aufbauend auf dieser Low-Level API implementiert Google die Standards Java Persistence API (JPA) und Java Data Objects (JDO). Im Open-Source-Bereich gibt es noch https://code.google.com/p/objectify-appengine/.

Google App Engine 1.5.5 freigegeben

Von http://code.google.com/p/googleappengine/wiki/SdkForJavaReleaseNotes:

  • We have increased the number of files you can upload with your application to from 3,000 to 10,000.
  • We have increased the size limit for a single file uploaded to App Engine from 10MB to 32MB.
  • We have increased the Frontend request deadline from 30 seconds to 60 seconds.
  • We have increased the online URLFetch maximum deadline from 10 seconds to 60 seconds. The default deadline remains at 10 seconds. The offline maximum deadline for URLFetch remains at 10 minutes.
  • We have increased the URLFetch Post payload from 1MB to 5MB.
  • App Engine now supports Cross Group (XG) transactions with the High Replication Datastore, which allow you to perform transactions across multiple entity groups. http://code.google.com/appengine/docs/java/datastore/transactions.html
  • We have added a graph to the admin console that displays the number of instances for which you will be billed.
  • In the XMPP API, getPresence() is deprecated in favor of using the inbound presence handlers documented inhttp://code.google.com/appengine/docs/java/xmpp/overview.html#Handling_User_Presence.
  • Fixed an issue in the Admin Console where the "Run Now" button did not work for tasks with a ‚-‚ in the name.
  • Fixed an issue to provide a better error message when a user tries to parse an HttpRequest’s input stream more than once in a request.
  • Fixed an issue to provide a better error message when using the Mail API to send email to an invalid user address.
  • Fixed an issue in the SDK where HttpServletRequest.getInputStream().read() always returned -1.http://code.google.com/p/googleappengine/issues/detail?id=5396
  • Fixed an issue where you could not schedule a cron job to run every 100 minutes.http://code.google.com/p/googleappengine/issues/detail?id=5861

Ein paar weitere Details: http://www.infoq.com/news/2011/10/Google-Cloud

App Engine 1.5.3 Update

Siehe http://googleappengine.blogspot.com/2011/08/app-engine-153-sdk-released.html, http://code.google.com/p/googleappengine/wiki/SdkForJavaReleaseNotes:

  • Blobstore API – We’ve removed the limits on the size of blob uploads. You can now upload files of any size, allowing your app to serve images, video, or anything your internet connection can handle.
  • Index retrieval – We’ve added the ability for you to programmatically retrieve the list of indexes you’ve currently defined in the datastore, as well as their statuses.
  • Datastore Admin – You can now enable the Datastore Admin function from the Admin Console. This will allow Java users to make use of this functionality, like deleting all entities of a certain kind, without having to upload a Python version of their application. And for Python developers, you no longer need to enable this in your app.yaml file.
  • HRD Migration Trusted Testers – We are seeking early adopters to try out an improved HRD migration tool that requires a read-only period relative to your datastore write rate (as opposed to your datastore size, which is how the current version behaves). Please see the release notes for more information.
  • Download app – Using the AppCfg download_app command, you can download any files that were uploaded from your war directory when you last updated the app version.

Google App Engine 1.4.3 veröffentlicht

Siehe http://googleappengine.blogspot.com/2011/03/announcing-app-engine-143-release_30.html. Änderungen in Java:

Java

  • Concurrent Requests: Until now, Java applications relied on starting additional instances to dynamically scale up for higher traffic levels. Now with support for concurrent requests, each application instance may serve multiple user requests at the same time. To start, ensure your application’s code is threadsafe, then enable concurrent requests by adding the <threadsafe> flag to your appengine-web.xml.
  • Java Remote API and Deferred API support: The Remote API andDeferred API libraries have been supported in Python for awhile, and now they can be used with Java, too! The Remote API allows you to perform operations on your application’s datastore from your local machine. This is particularly useful for work that is not well-suited to App Engine’s request/response model. The Deferred API allows users to more easily write and execute ad hoc tasks. Our docs contain more information and examples on how to use the Remote API and Deferred API in Java App Engine.
New and changed APIs
  • Files API: The new Files API in Python and Java allow you to pragmatically read and write data using Blobstore. This API can be used to generate reports, export data, or do anything that your heart desires that requires large, binary objects.

 

File-IO finde ich spannend, noch toller wäre es gewesen, wenn sich Google an NIO2 halten würde.

Google App Engine 1.4

Wie im Blog http://googleappengine.blogspot.com/2010/12/happy-holidays-from-app-engine-team-140.html zu lesen, erblickt die Version 1.4 das Adventlicht. Die News in Kürze:

  • The Channel API – A bi-directional channel for communicating directly with user browsers by pushing notifications directly to the JavaScript running on the client, eliminating the need for polling. This service makes it easy to build real-time applications such as multi-player games, chat rooms, or any collaboration centric app and is built on the same Google infrastructure that powers Google Talk.
  • Always On – For high-priority applications with low or variable traffic, you can now reserve instances via App Engine’s Always On feature. Always On is a premium feature costing $9 per month which reserves three instances of your application, never turning them off, even if the application has no traffic. This mitigates the impact of loading requests on applications that have small or variable amounts of traffic.

Screenshot of the Instances page in the App Engine Admin Console with Always On enabled.

  • Warm Up Requests – This feature reduces time to serve requests by anticipating the need for more instances and loading them before user traffic is sent to the new instance. It can be enabled for all applications through app.yaml or appengine-web.xml and is enabled by default for applications that have purchased Always On. Once enabled, warm up requests will be sent whenever possible to load new instances of your application before it begins serving user traffic.

Der erste Teil ist oft unter dem Stichwort Comet geführt.

Weitere Änderungen:

  • No more 30-second limit for background work – With this release, we’ve significantly raised this limit for offline requests from Task Queue and Cron: you can now run for up to 10 minutes without interruption.
  • Increased API Call Size Limits – A new API architecture has allowed us to start lifting the 1MB size limits on many of the App Engine APIs. To start, the following APIs have been changed:
    • Response size limits for URLFetch have been raised from 1MB to 32MB.
    • Memcache batch get/put can now also do up to 32MB requests.
    • Image API requests and response size limits have been raised from 1MB to 32MB.
    • Mail API outgoing attachments have been increased from 1MB to 10MB

10 Minuten würden mir schon helfen, Daten in die BigTabe zu laden…

Diskussion, warum die Google App Engine for Java nix ist

Ein GAE-Nutzer diskutiert unter http://www.carlosble.com/?p=719 und lesenswert sind Kommentare (wobei mir das oft ein wenig zu grob und prollig ist). Die Kritikpunkte decken sich mit meinen Erfahrungen. Ich habe eine größere Web-Anwendung mit GWT für GAE/J gebaut (mit Objectify und wirklich an der Modellierung gefeilt), aber letztendlich fand ich den Datastore für meine Aufgaben zu langsam. Ich mag den Dienst, aber man schon ganz schön tricksen und erst nach vielem Rumbiegen und Designänderungen geht es dann irgendwie. Und das ist in meinen Augen das Problem, dass doch wieder die Technologie (und ihre Beschränkungen) das Design fundamental steuert. Letztendlich habe ich meine Web-Anwendung auf einen eigenen Server gesetzt und bin von GAE/J weggegangen. Vieles konnte ich rausschmeißen und alles wurde simpler und das DDD scheint jetzt wieder klarer durch.

SimpleDS 1.0 ist fertig

Entwickler auf der GAE/J, die nicht mit JPA oder JDO arbeiten – was die Regel sein dürfte? – können die neuste Version von SimpleDS nutzen.

In der Vergangenheit habe ich ein GAE/J-Projekt mit http://code.google.com/p/objectify-appengine/ realisiert und mich gegen SimpleDS entschieden. Beides haben etwas unterschiedliche Philosophien, wie sie mit IDs/Keys umgehen. Frühere Blog-Eintrage verlinken zu beiden und zu Seiten mit einer Diskussion der Unterschiede.

com.google.appengine.api.datastore.* Typen für GWT serialisieren

Wer Datentypen wie com.google.appengine.api.datastore.Text in seiner Bean nutzt kann die Datentypen serialisieren. Wenn man nun eine Bean mit zum Beispiel dem Typ Text nach GWT serialisiert, der wird bemerken, dass GWT diese Datastore-Datentypen nicht unterstützt. Nun reicht es nicht, eine Kopie von etwa der Klasse Text anzufertigen und in den Quellordner zu setzen, da die Klasse nicht im client-Paket ist. Stattdessen ist ein etwas anderes Vorgehen nötig. Denn um Java-Klassen auch außerhalb vom client-Paket platzieren zu können, ist in der XML-Datei in Eintrag wie der folgende nötig;

<super-source path=""/>

Um das für die Datastore Klassen nicht selbst schreiben zu müssen, können wir auf die Implementierung unter http://www.resmarksystems.com/code/ zurückgreifen. Wir

  1. setzen <inherits name="com.resmarksystems.AppEngineDataTypes"/> in unsere GWT-XML-Datei und
  2. laden http://www.resmarksystems.com/code/appengine-utils-client-1.0.jar und setzten das Jar in unsern lib-Ordner

Das war’s schon. Serverseitig muss nichts gemacht werden.

Google App Engine Prerelease 1.3.4 SDK

Die Neuerungen in Kürze:

– Client side bulkloader available with the Python SDK that has a new  configuration syntax and wizard for easier import/export with the datastore. Can be used by enabling remote_api in your Java application
– Applications can now be configured to authenticate with OpenID by selecting the OpenID option when creating your application in the admin console. http://code.google.com/p/googleappengine/issues/detail?id=248. http://code.google.com/p/googleappengine/issues/detail?id=56
– New API to allow App Engine apps to act as OAuth service providers. ttp://code.google.com/p/googleappengine/issues/detail?id=919
– The version update check in the Java SDK now uses https.
– Allow full access to javax.el.* . http://code.google.com/p/googleappengine/issues/detail?id=3157
– Increased the timeout during deployment to 15 minutes
– Fixed an issue with JPA where an illegal cast exception was thrown during the fetch of integer fields
– MemcacheService.setNamespace() is deprecated in favor of
  MemcacheServiceFactory.getMemcacheManager(namespace)
– Support in the SDK for Java 1.5 is being deprecated. These warnings now appear  when starting the SDK

Sehr interessant ist die Remote-API (http://blog.notdot.net/2010/05/Behind-the-scenes-with-remote-api). Über Beispiele in Java werde ich Zukunft berichten.

SimpleDS 1.0 RC für die GAE/J

Dass die Low-Level-API nicht so tolle ist, habe ich unter anderem schon hier eine Alternative genannt. Eine andere ist SimpleDS, von der nun der erste Release Candidate raus ist. Siehe auch die 1.0-Ankündigung. Features:

Version 1.3.3 der Google App Engine

Die Neuerungen im Überblick:

„Appstats for Java“ Profiling von Web-Requests für Google App Engine

Die Appstats for Java http://code.google.com/intl/de/appengine/docs/java/tools/appstats.html sind ein Servlet-Filter, die Zeiten für die Requests messen und alles, was mit einem Request verbunden ist. Später lässt sich das ganze auch Visualisieren. Der Blog-Eintrag http://googleappengine.blogspot.com/2010/03/easy-performance-profiling-with.html beschreibt das und liefert ein paar Screenshots mit.

http://1.bp.blogspot.com/_dLfQMJsmsaI/S7NKKyRM5-I/AAAAAAAAAEA/rfaOPZXtr80/s1600/Picture+4.png

http://1.bp.blogspot.com/_dLfQMJsmsaI/S7NKQChvYYI/AAAAAAAAAEI/xtrznFfj05g/s1600/appstats2.png