Als ich vor einigen Jahren das erste Mal die PaaS-Angebote von Heroku (cloud application platform) und Google (App-Engine) ausprobierte, war ich von den Möglichkeiten fasziniert:
- Installation und Betrieb deiner Webseite/Webanwendung mit Datenbank in der Cloud
- keine eigene Infrastruktur und damit keine eigenen Server-Konfigurationen
- kleine Webanwendungen lassen sich kostenlos bei den Anbietern betreiben
- automatisches Hochskalieren bei Last
- und alles so einfach und bequem !!!
Natürlich gab/gibt es auch ein paar Nachteile gegenüber dem Betrieb eines eigenen Servers:
- Programmiersprache ist nicht frei wählbar (früher: Ruby bei Heroku, Python und Java bei Google)
- Datenbank-Features sind beschrängt, auch die Frage ob SQL- oder NoSQL-Datenbank
- bei den sonstigen Server-Komponenten (wie Messaging) ist man auf die Auswahl des Anbieters angewiesen
- höhere Kosten als bei einem eigenen Server, wenn die Last steigt oder mehr Speicherplatz benötigt wird
- Datenschutzprobleme, falls sich Benutzerdaten in der Cloud außerhalb Europas befinden
Ich hatte damals den Eindruck, dass man sich bei der Architektur der eigenen Anwendung sehr verbiegen muss, damit sie in der entsprechenden Umgebung auch läuft. Trotzdem bieten die PaaS-Angebote natürlich tolle Möglichkeiten, entwickelte Anwendungen schnell im Netz zu veröffentlichen. Und daher habe ich jetzt mal wieder Heroku ausprobiert – es hat sich einiges getan und Heroku fühlt sich wirklich gut an…
Zunächst einmal bietet Heroku neben Ruby jetzt einige Programmiersprachen mehr an: Node.js, Clojure, Java, Python und Scala. Außerdem hat man die Wahl zwischen vielen Zusatzkomponenten (Addons), die natürlich teilweise (eher größtenteils) kostenpflichtig sind (z.B.: Postgres-DB, MySQL, MemCache, MongoDB, Cassandra, Solr).Nach ein paar Schritten hat man schon seine erste Java-Webanwendung auf Heroku deployt. Ich habe mich an der Java-Dokumentation von Heroku gehalten (hier), was auch auf Anhieb funktionierte. Daher biete ich jetzt nur eine kurze Zusammenfassung:
- Java 6 und Maven 3 auf seinem lokalen Sytem installieren
- Heroku-Account hier anlegen
- Heroku-Toolbelt hier herunterladen und installieren (enthält CLI-Client, Foreman und Git)
- auf der Console in ein Verzeichnis für neues Heroku-Projekt wechseln
- bei Heroku einloggen:
heroku login
- Maven Projekt mit Jetty-Server anlegen, wie hier beschrieben
- Datei
.gitignore
erstellen mit Inhalttarget
, damit das target-Verzeichnis von Git ignoriert wird - Projekt mit Maven bauen (das muss natürlich erfolgreich sein):
mvn package
- den Port der Anwendung angeben und mit Maven die Anwendung lokal starten – auf Mac/Linux:
export PORT=5000 java -cp target/classes:"target/dependency/*" HelloWorld
- mit dem Browser die lokale Anwendung kontrollieren:
http://localhost:5000
- Datei
Procfile
für Foreman erstellen mit Inhalt:web: java -cp target/classes:"target/dependency/*" HelloWorld
- lokales Git-Repository für das Projekt erstellen und alles einchecken:
git init git add . git commit -m "my first heroku project"
- Heroku-App auf dem Heroku-Server erstellen:
heroku create
- die Anwendung auf den Server übertragen und starten:
git push heroku master
- in der Ausgabe den Server heraussuchen und im Browser öffnen (juhu – alles hat geklappt)
beispielsweise: http://sharp-wind-2356.herokuapp.com/
Auf der Konsole kennt Heroku einige nette Befehle, mit denen man sich einen Überblick zu seiner Anwendung verschaffen kann:
heroku ps # Prozesse anzeigen heroku logs # Log-Datei anzeigen heroku open # Browser öffnen mit der Anwendung heroku version # Version des Heroku-Clients heroku info # Informationen zu der Anwendung anzeigen heroku config # Konfiguration der Anwendung anzeigen heroku addons # Addons der Anwendung anzeigen heroku apps:rename # Anwendung umbenennen
Und wenn man Änderungen am Quellcode der Anwendung vorgenommen hat, genügt ein Einchecken der Änderungen in Git und ein erneutes Hochladen:
git add . git commit -m "my changes" git push heroku master
Als Nächstes steht natürlich ein eigener kleiner Praxis-Test an. Dafür habe ich versucht, meinen OSM-Locationpicker bei Heroku zu installieren. Die zuvor genannten Schritte und ein paar kleinere Anpassungen waren dafür nötig:
- Erstellen einer Jetty-Startklasse, die die Webanwendung startet:
package de.bruns.example.osm.locationpicker; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.webapp.WebAppContext; public class LocationPickerJetty { public LocationPickerJetty() throws Exception { int port = 8080; try { port = Integer.valueOf(System.getenv("PORT")); } catch (NumberFormatException e) { e.printStackTrace(); } WebAppContext context = new WebAppContext(); Server server = new Server(port); context.setServer(server); context.setDescriptor("src/main/webapp/WEB-INF/web.xml"); context.setResourceBase("src/main/webapp"); context.setContextPath("/"); context.setParentLoaderPriority(true); server.setHandler(context); server.start(); server.join(); } public static void main(final String[] args) throws Exception { new LocationPickerJetty(); } }
- Maven-Konfiguration (pom.xml) um folgende Einträge erweitern:
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>8.1.4.v20120524</version> </dependency> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.4</version> <executions> <execution> <id>copy-dependencies</id> <phase>package</phase> <goals><goal>copy-dependencies</goal></goals> </execution> </executions> </plugin>
- Die Ergänzungen habe ich bei meinem Github-Projekt https://github.com/me4bruno/example-osm-locationpicker hinzugefügt und damit sollten die nächsten Schritte auch funktionieren.
- Projekt von Github holen, lokal bauen und starten:
git clone git://github.com/me4bruno/example-osm-locationpicker.git cd example-osm-locationpicker mvn package export PORT=5000 java -cp target/classes:"target/dependency/*" de.bruns.example.osm.locationpicker.LocationPickerJetty
Prüfen, ob der OSM-Locationpicker lokal funktioniert: http://localhost:5000
- Procfile erstellen, neues lokales Git-Repository erstellen und die Sourcen committen:
rm -rf .git echo "target" > .gitignore echo "web: java -cp target/classes:\"target/dependency/*\" de.bruns.example.osm.locationpicker.LocationPickerJetty" > Procfile git init git add . git commit -m "my second heroku project"
- Heroku-Projekt erstellen und umbenennen, Dateien hochladen und Webanwendung starten:
heroku create heroku apps:rename osm-locationpicker git push heroku master heroku open
- Auf http://osm-locationpicker.herokuapp.com/können wir uns unser Ergebnis anschauen:
Heroku bietet übrigens auch die Verwendung von kostenlosen Postgres-Datenbanken an. Das beschreibe ich sicherlich später mal – mit diesen Anweisungen kann man ja schon einige nette Sachen machen.