Einträge der Kategorie ‘Developer Blog’

04.10.2010

iTosa’s Weg in die Cloud – Cloud Engines

Wie im vorangegangenen Post beschrieben standen wir vor der Wahl in welcher CloudEngine unser Formular/Umfragen-Dienst cloums.com das Licht der Welt erblicken sollte.

Mit der bisherigen Vorarbeit in HTML, CSS und JS konnte das Backend noch relativ frei gewählt werden.

Alle Anbieter rechnen ihre Leistungen nach Verbrauch ab. Wobei eine laufende Instanz bei Amazon und Microsoft unabhängig von deren Nutzung eben 24Stunden/Tag abgerechnet wird. Dazu gehören CPU-Stunden (gestaffelt nach Leistung), Speicherplatz (Größe und Transfer), Datenbank, Requests/Connections und Datenübertragung.
Einige Leistungen können auch als Paket mit festgelegter Inklusivleistung bezogen werden.

Alle Anbieter stellen eine Service-Infrastruktur zur Verfügung die Datenbanken, Storage und Managementfunktionen bietet.

Google App Engine, What is Google App Engine?

  • Platform as a Service
  • Unterstützt Python (2.5.2) mit Django 0.96, wobei Django aktualisiert werden kann
  • Unterstützt Java 6 virtual machine (JVM)
  • mittels Quercus (PHP Java Implementation) ist wohl auch PHP möglich.
  • Läuft in einer Sandbox,

    These limitations allow App Engine to distribute web requests for the application across multiple servers, and start and stop servers to meet traffic demands

  • Kostenfreie Nutzung mit bis zu 43 Millionen Request/Tag, 1Gb Storage, siehe Details
  • Vergleichbar mit Shared-Hosting Umgebung mit fester Python- und Javaunterstützung in einem bestimmten (beschränkten) Funktionsumfang. Wobei die Beschränkungen mit einem hochoptimierten Pythoninterpreter und einer skalierbaren Architektur einhergehen und die Abrechnung auf Nutzungsbasis erfolgt.
  • Berechnet werden viele Leistungen nach Nutzung, z.B. CPU-Hour, Storage etc.

Amazon Elastic Compute Cloud (Amazon EC2)

  • Infrastructure as a Service
  • Virtuelle Server mit vollen Administrationsrechten
  • Vorkonfigurierte Amazon Machine Images (AMI) mit verschiedenen Betriebsystemen (Linux, Windows) als Datenbankserver(MySQL, MSSQL, Oracle, DB2), Webserver (Apache, IIS) und einer Vielzahl weiterer Optionen
  • Dauerhafte Datenspeicherung mittels
    • Datenbanken
      • Amazon SimpleDB
      • Amazon Relational Database Service (RDS)
    • Virtuelle “Festplatten” zum Einbinden in die virtuellen Rechner
      • Amazon Elastic Block Store (Amazon EBS)
  • Vergleichbar mit virtuellen Servern bei anderen Hostern. Wobei sehr flexibel, innerhalb von Minuten weitere Instanzen gestartet und genauso schnell wieder beendet werden können. Die Bezahlung erfolgt für laufende Instanzen pro Stunde.
  • Automatisches Skalierung über Amazon CloudWatch (Auto Scaling)
  • Kleinste Instanz (Small) : 1 EC2 Compute Unit – 1.7 GB (Memory) – 160 GB (temp. Storage)
  • Die Preise variieren von 0,095 USD pro Stunde (Small mit Linux) bis zu 1,16 USD (CPU Extra Large, Windows) und 2,88 USD (Memory Quadruple Extra Large, Windows). Preise, Preisrechner
  • Bei reservierten Instanzen (Reserved Instances) in Form eines Laufzeitvertrages (ab 227.50 USD (1 Jahr) / 350 USD (3 Jahre)) sinkt der Stundenpreis um fast 50%.
  • Keine kostenfreie Testvariante

Microsoft Windows Azure

  • Infrastructure/Platform as a Service
  • Virtuelle Windowsserver in den Rollen: (Understanding Roles)
    • als Webserver mit IIS + ASP.NET (web role)
    • als Applikationsserver mit .NET Framework 3.5 SP1 (worker role)
  • Webserver erweiterbar durch FastCGI (z.B. PHP, URL Rewrite Module), Windows Azure SDK for PHP Developers
  • Kleinste Instanz (Small) : 1.6 GHz (CPU) – 1.75 GB (Memory) – 225 GB (temp. Storage)
  • Microsoft rechnet wie Amazon laufende Instanzen ab. Preise pro Stunde ab 0.12 USD (small compute instance). Es gibt auch Laufzeitverträge für 6 Monate, mit denen fast 50% eingespart werden können. Windows Azure Platform Offer Comparison Table
  • Es gibt ein kostenfreies Introductory Special mit 25 Stunden/Monat welches aber am 31. Oktober ausläuft
  • Die Anzahl der Instanzen wird in der Konfigurationsdatei () festgelegt und kann im Verwaltungsbereich zur Laufzeit angepasst werden. Über die Management API kann die Anzahl der Instanzen auch über eigene Scripte angepasst werden.
  • In der WebRole Vergleichbar mit einen Shared-Windows-IIS-Hosting mit FastCGI unterstützung.

And the winner is ..

Aufgrund folgender Kriterien:

  • optimierte Codeausführung
  • automatische Skalierung
  • echtes “Pay as you Use”, nur die Nutzung und nicht 24h-Bereitschaft wird bezahlt
  • kostenfreie Nutzung mit bis zu 43.000.000 Request/Tag
  • Kennenlernen von Python. Wir hätten sonst PHP und/oder .NET-Code weiterverwendet.

haben wir uns für die Google App Engine entschieden.

Doch ein Wermutstropfen bleibt:

  • Der App Engine Datastore (Googles BigTable) ist keine relationale Datenbank. Bestimmte Filter und komplexe Abfragen werde nicht unterstützt und müssen auf anderem Wege umgesetzt werden. Diese Einschränkung trifft uns schon deutlich, da wir in der Welt der relationalen Datenbanken heimisch sind.
    Die Auslegung des Datastore auf Skalierung und hohe verteilte Leistung erfordert eben andere Herangehensweisen.

Unser Beschluss betrifft aber nur die ersten Schritte von cloums.com, wir werden nach der Google App Engine auch die anderen Cloud Anbieter ausprobieren.
Insbesondere das datenbanklastige iTosa wird sich eher in der relationalen Datenbankwelt heimisch fühlen. Auch die Weiterverwendung unserer PHP/.NET-Basis ist nur bei Amazon und Microsoft möglich.

 
26.09.2010

iTosa’s Weg in die Cloud

Am 17.09. starteten wir in Hamburg auf den CloudCamp das iTosa Schwesterprojekt http://cloums.com.

In diesem und den folgenden Blogposts werden wir den begangenen Weg beschreiben, von der Auswahl der Cloud Engine, bis zum Betrieb der Cloud Application.

Die Idee für Cloums entstand ganz pragmatisch. Der bestehende Offline-Konfigurator (.NET) sollte durch einen Online-Konfigurator ersetzt werden um die Anforderungen für iTosa auf einen Browser zu reduzieren.

Dazu mussten wir die bestehende Anwendung, die schon von Beginn an aus selbstgezeichneten Controls bestand, nach HTML, CSS und JS portieren.

Als ersten Schritt bot sich die Umsetzung der WYSIWYG-Formularansicht mittels HTML und CSS an:
Bild aus Tutorial Adressbuch

Kombiniert mit dem in iTosa geplanten, aber nicht umgesetzten Drag’n'Drop-Katalog, war Cloums praktisch fertig und der Designer verwendbar.
Nun fehlte nur noch das Server-Backend das in der Lage sein musste die erstellten Formulare abzuspeichern.

Die bisherigen Schritte folgen also konsequent der Umsetzung des iTosa-Konfigurators in eine Browserumgebung.
An dieser Stelle war nur eine kleiner Schlenker in Richtung Cloud erforderlich und schon hatten wir einen Formular-Designer in der Cloud, CloudForms, eben cloums.

Im nächsten Post geht es um die Auswahl der Cloud Engine, zur Auswahl standen nach kurzer Recherche:

 
19.07.2010

Optimierung der Webseite

Angeregt durch einen iX-Artikel werden wir weitere Optimierungen an den iTosa-Applikationen vornehmen.

Begonnen haben wir zunächst mit der Ist-Analyse mittels der Firefox-Plugins:

Enthalten in diesen Tools sind auch ein paar Optimierungswerkzeuge, vor allem aber Hinweise zu Verbesserungsmöglichkeiten.

Einige der Punkte:

  • Reduzierung der HTTP-Request - Zusammenfassung/Reduzierung der .js, .css und Image-Dateien
  • Schnellerer Seitenaufbau – CSS so früh wie möglich, JS so spät wie möglich einbinden
  • Geringere Dateigröße – Übertragungskomprimierung, JS/CSS-Verkleinerung(löschen von Kommentaren, Leerzeichen etc.), Bildkomprimierung(verlustfrei)
  • Cacheunterstützung – Gültigkeitsheader mit langer Laufzeit

Vieles berücksichtigen wir zwar schon in unseren Projekten, die Reduzierung und Zusammenfassung der Dateien werden wir aber noch verbessern. Die CSS/JS-Positionierung war uns bisher unbekannt.

Es gibt noch weitere Ansätze, z.B. die Plazierung der Images in einem CDN (Content Delivery Network) oder einfach unter einer Subdomain.
Ersteres sind Dienste die sich auf die schnelle Auslieferung von Dateien spezialisiert haben. Die Subdomain ist ein Trick um die Browserbeschränkung der gleichzeitigen Downloads von einem Server zu umgehen.

Dieser Ansatz klingt zwar verlockend, doch verträgt er sich nicht unbedingt mit einer SSL-gesicherten Verbindung. Wir hatten früher schon testweise die JavaScript-Bibliothek prototype.js vom Google Server bezogen. Leider verursacht das eine Mixed-Content-Warnung beim Benutzer.

 
31.05.2010

SimpleXML Text und XML gemischt

Ein Teil unseres Generators verarbeitet ein XML-Template und erzeugt daraus PHP-Code.
Unsere Lösung ersetzt aber nicht nur die Platzhalter sondern hat auch Aspekte einer DSL.

Das nachfolgende Beispiel macht Probleme bei der Verarbeitung mit SimpleXML.
Der erste code-Block enthält neben dem Code-Template auch noch weitere XML-Anweisungen.

<function name='setFieldRole_[#role.name]' modifier='public'>
	<param name='value'/>
	<code>
	parent::setAttribute('Role_[#role.name]', $value);
		<foreach in='role.pk' key='' value='pk'>
			<code>
			parent::setAttribute('Role_[#role.name].[#pk.name]', $value);
			</code>
		</foreach>
	parent::store();
	</code>
</function>

Mit SimpleXML lassen sich beide verarbeiten, allerdings nur getrennt.
Der Textteil im code-Block wird so ausgegeben:

                parent::setAttribute('Role_[#role.name]', $value);
                parent::store();

Das Iterieren über die Unterknoten des code-Knotens liefert den foreach-Knoten aber ohne Positionierung im Text.
foreach wird dadurch nicht zwischen den beiden Einzelanweisungen (setAttribute(), store()) ausgeführt, sondern am Anfang oder am Ende.

Eine Lösung dieses Problems war die Verarbeitung dieser Bereiche mittels DOM, wie hier angeregt SimpleXML : Edge Conditions wurde.

Der Quelltextausschnitt dazu:

    $dom = dom_import_simplexml($xml);
    foreach($dom->childNodes as $child){
        if($child->nodeType == XML_TEXT_NODE)
            $this->writeText($child->nodeValue);
        else
            $this->proceedNode(simplexml_import_dom($child));
    }

Dieses Iterieren im DOM liefert jeden Textteil einzeln, so dass wir nach der Verarbeitung des foreach-Knotens unser gewünschtes Resultat erhalten:

parent::setAttribute('Role_[#role.name]', $value);
parent::setAttribute('Role_[#role.name].[#pk.name]', $value);
parent::store();