windowsAzure: Web.config settings

To optimize the performance of my WindowsAzure web role I analysed it with the firefox plugin page speed. To pass the several tests I needed to enhance the following settings.

Leverage browser caching:

<system.webServer>
    <staticContent>
      <clientCache httpExpires="Sun, 29 Mar 2020 00:00:00 GMT" cacheControlMode="UseExpires" />
    </staticContent>

I changed the above setting to:

<system.webServer>
    <staticContent>
      <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00"  />
    </staticContent>

Because it is strongly not recommend to use high expiration dates, because you can not influence client or proxy cache if the file is already cached. In this example it set it to 1 day.

More Information here.

Specify a Vary: Accept-Encoding header:
<system.webServer>
	  <httpProtocol>
	    <customHeaders>
		    <remove name="Vary"></remove>
		    <add name="Vary" value="Accept-Encoding"></add>
	    </customHeaders>
	  </httpProtocol>

Also I changed here a little bit:

<system.webServer>
	  <httpProtocol>
	    <customHeaders>
		    <remove name="Vary"></remove>
		    <add name="Vary" value="Accept-Encoding, Cookie"></add>
	    </customHeaders>
	  </httpProtocol>

Cookie means in this case to use a different cache version for each session.

EDIT: I removed the “Cookie”-Setting again, because it slows down every page request up to 2  Seconds!

More information here.

Enable compression:

<system.webServer>
    <staticContent>
      <remove fileExtension=".js" />
      <mimeMap fileExtension=".js" mimeType="text/javascript" />
    </staticContent>

    <httpCompression
        directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files"
        cacheControlHeader="max-age=86400"
			  noCompressionForHttp10="false"
			  noCompressionForProxies="false"
			  sendCacheHeaders="true"
                          minFileSizeForComp="0">
      <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
      <dynamicTypes>
        <add mimeType="text/*" enabled="true" />
        <add mimeType="message/*" enabled="true" />
        <add mimeType="application/x-javascript" enabled="true" />
        <add mimeType="*/*" enabled="false" />
      </dynamicTypes>
      <staticTypes>
        <add mimeType="text/*" enabled="true" />
        <add mimeType="message/*" enabled="true" />
        <add mimeType="application/javascript" enabled="true" />
        <add mimeType="*/*" enabled="false" />
      </staticTypes>
    </httpCompression>
    <urlCompression doStaticCompression="true" doDynamicCompression="true" />

Not that httpCompression is already enabled by default, but the default setting for minFileSizeForComp ist 2700kB, so small files will be ignored. Furthermore I disabled the compression for HTTP1.0 and Proxies, because older browser sometime have problems with it.

The modification of the mimeMap is done because of the different mimeTypes for JavaScript, so we give all .js files the same mime type which will be compressed.


WindowsAzure: Remote Desktop

I needed some research to find out how to configure a WindowsAzure web role manually to activate Remote Desktop.

Here are the settings:

ServiceDefinition.csdef:

 <WebRole>
   ...
   <Imports>
     <Import moduleName="RemoteAccess" />
     <Import moduleName="RemoteForwarder" />
   </Imports>
 </WebRole>

Each role of the deployments which needs RDP requires the module “RemoteAccess”. Only one role needs to import the module “RemoteForwarder”.

ServiceConfiguration.cscfg

 <Role name="WorkerRole">
   <Instances count="2" />
   <ConfigurationSettings>
     ...
     <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.Enabled" value="true" />
     <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountUsername" value="jimoneil" />
     <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountEncryptedPassword" value="ENC_PASSWORD" />
     <Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountExpiration" value="2011-01-27T23:59:59.0000000-05:00" />
    <Setting name="Microsoft.WindowsAzure.Plugins.RemoteForwarder.Enabled" value="true" />
   </ConfigurationSettings>
   <Certificates>
     <Certificate name="Microsoft.WindowsAzure.Plugins.RemoteAccess.PasswordEncryption"
                  thumbprint="CERTIFIKATE_THUMBPRINT"
                  thumbprintAlgorithm="sha1" />
   </Certificates>
 </Role>

“RemoteForwarder” only needs to be activiated for the forwarder role. Follow the link below for a generate password how-to. The thumbprint can be found in the management portal.

Links


PHP: Symfony Framework Pros&Contras

Im Folgenden werden u.a. die Pros und Contras des Symfony-Frameworks vorgestellt, welches für viele als eine mögliche Alternative zur aktuellen Lösung angesehen wird.

Definition

Das Symfony-Framework wurde von Sensio Labs entwickelt. Es kapselt jahrelange Erfahrung der PHP-Entwicklung und vereinfacht enorm die Entwicklung mittlerer bis großer Web-Projekte. Es ist aus der Idee heraus entstanden das perfekte Tool für Web-Entwickler zu kreieren die Kunden mit hoch performanten Ansprüchen bedienen.

Symfony basiert auf dem MVC Design-Pattern und versucht die Entwickler selbst dazu zu bringen sauberen, gut strukturierten Code zu produzieren. D.h. in Templates nur Präsentationslogik, Controller lediglich als eine Art schlankes Batch-Script zu gebrauchen und die Businesslogik in den Modell- und Form-Klassen zu hinterlegen.

Es bietet zahlreiche Hilfsmittel um die Entwicklungszeit von komplexen Web-Applikationen stark zu reduzieren. Außerdem sind gängige Aufgaben automatisiert, so dass sich die Entwickler mehr auf die Anwendungslogik konzentrieren können. Ziel ist es das Rad nicht immer wieder neu zu erfinden wenn eine neue Web-Applikation entwickelt wird.

Symfony ist komplett in PHP geschrieben und hat sich bereits in zahlreichen Real-World-Projekten bewiesen. Darunter auch High-Demand Webseiten (z.B. delicious.com und answers.yahoo.com, dailymotion.com).

Symfony Features

Symfony wurde entwickelt um die folgenden Anforderungen zu erfüllen:

  • Einfach auf den gängigsten Plattformen zu installieren und konfigurieren.
  • Datenbank-Engine-Unabhängig.
  • Überwiegend einfach zu benutzen aber dennoch flexibel genug um komplexe Klassen zu adaptieren.
  • Verträglich mit den meisten Web-Best-Practises.
  • Stabil genug für Langzeit-Projekte.
  • Sehr lesbarer Code mit phpDocumenter-Kommentaren für einfache Wartung.
  • Einfach zu erweitern. Integration von anderen Code-Bibliotheken ist möglich.
  • Ein Mal geschriebener Code soll möglichst einfach wiederverwendbar sein (Components, Slots).

Webprojekt-Features

  • Symfony Autoloader für .class.php Dateien in lib-Verzeichnissen.
  • Parameter-Holder für saubere Übergabe von http-Request Parametern mit Getter und Setter.
  • Internationalisierungs-Ebene.
  • Die Präsentations-Ebene ist Template-basiert und unterstützt AJAX-Funktionalitäten (jQuery).
  • Formulare lassen sich automatisiert validieren und einfach wiederverwenden.
  • Ausgabefilterung schätzt vor Cross-Site-Scripting durch korrupte Daten.
  • Die Cache-Management-Features reduzieren die Bandbreitennutzung und den Server-Load.
  • Authentifizierungs- und Rechtefeatures vereinfachen die Erstellung von geschätzten Bereichen und ermöglichen Benutzer-Sicherheits-Management.
  • Routing und Smart URLs machen Seitenadressen Suchmaschinen tauglich.
  • E-Mail-Management (SWIFT-Mailer).
  • Benutzerfreundliche Listen durch automatisch generierte Pager, Sortierer und Filter.
  • Factories, Plugins und Events ermöglichen einen hohen Grad der Erweiterbarkeit.

Entwicklungsumgebung und Werkzeuge

Symfony beinhaltet bereits standardmäßig verschiedene Entwicklungsumgebungen und bietet verschiedene Werkzeuge und automatisierte Tasks für gängige Aufgaben der Software-Entwicklung:

  • Code-Generierungs-Werkzeuge sind bestens geeignet für Prototypen und Administrationen.
  • Das eingebaute Unit- und Functional-Testing Framework bietet Tools für Test-Driven-Development-Unterstützung.
  • Das Debug-Panel beschleunigt das Debugging durch das Anzeigen vieler wichtiger Seiten-Informationen die ein Entwickler benätigt (SQL Queries, Ladezeiten, Chaching-Informationen, http-Parameter, Logs, Umgebungsvariablen etc.).
  • Kommandozeilen-Schnittstellen automatisieren das Deployment zwischen zwei Servern.
  • Live-Änderung an den Konfigurationen sind möglich und effektiv.
  • Die Logging- und Exception-Features geben Administratoren Transparenz über die Anwendungsaktivitäten.

Symfony vs. Zend

An dieser Stelle muss zuerst erwähnt werden, dass sich beide Frameworks wohl kaum vergleichen lassen, da sie unterschiedlicher nicht sein könnten.

Wie das .NET Framework ist das Zend Framework (ZF) eine Ansammlung von Funktionen welche zusammen gute Schnittstellen bereitstellen um die komplexesten Anforderungen, die regelmäig auftreten, von Webentwicklern zu befriedigen. Der größte Vorteil aber auch Nachteil von ZF ist, dass es keinen bestimmten Weg bzw. Konventionen vorgibt wie die Anforderungen zu bewerkstelligen sind.

Bei ZF gibt es kaum Code-Generierung und Konfigurationen werden alle im Front-Controller vorgenommen. Symfony (SF) generiert anhand des DB-Schemas eine Menge Code, welcher zunächst die Code-Basis aufbläht aber den Entwicklern viel Zeit erspart. Konfigurationen (wie Authentifizierung, Caching, Layout uvm.) können in hierarchischer Erbreihenfolge von Applikation über Module bis hinunter zur einzelnen Action über YAML-Files vorgenommen werden. ZF lässt einem bei der Ordnerstruktur alle Freiheiten, wohingegen symfony eine strikte Struktur vorgibt. Dies trägt am Anfang nicht zu einer höheren Lernkurve bei, aber die Einheitlichkeit lässt die Entwickler später sehr leicht im Code navigieren.

Symfony hat eine sehr gute und aktuelle online Dokumentation sowie daraus entstandene Begleitbücher. Darüber hinaus ist die Community sehr aktiv und auch bei komplexeren Problemen sehr hilfreich. ZF verfügt leider nicht über so viel Dokumentation und richtet sich sehr stark an die erfahreneren Entwickler die schon sehr geübt sind mit den komplexeren Aspekten der objektorientierten Programmierung.

Im Gegensatz zu ZF hat SF eine sehr aktive Plugin- und Erweiterungs-Community. Man kann sogar ZF-Funktionalitäten über das Zend-Framework-Plugin in Symfony integrieren.

Symfony 1.4 vs Symfony2

Sensio Labs veröffentlicht ein neues Major-Release Symfony2.0, worauf dieser Abschnitt kurz eingeht:

Unterschiede (soweit bekannt):

  • Neues Template-System (Twig), bisher PHP-Files die von den Actions die Template-Variablen erben.
  • Partials und Page-Templates werden nicht mehr unterschieden.
  • Templates unterstützen Vererbung.
  • Actions entsprechen Components (Components sind wiederverwendbar).
  • Kein sfWebRequest Objekt mehr. Über das Routing werden Parameter direkt übergeben.
  • Mit Doctrine 2 wird der Active Record Pattern durch den Entity Pattern ersetzt.
  • Nur noch einen Entity-Manager statt einer Factory (Table Object) pro Model.
  • Logger und Caches von Zend Framework.
  • Für Unit-Tests werden statt Lime PHPUnit Tests verwendet.
  • Mit PHP 5.3 Verwendung von Namespaces etc.
  • Forms bestehen nicht mehr aus Widgets und Validatoren sondern aus Feldern mit Renderern und Validatoren).

Es stellt sich die Frage ob so kurz vor einer grundlegend neuen Version nicht schon diese verwendet werden sollte. Nun, auf der Projekt-Homepage selbst steht, dass Symfony2.0 noch nicht reif ist für den produktiven Einsatz. Das Final-Release ist für ~März 2011 geplant. Es wird empfohlen neue Projekte, mindestens bis zu diesem Termin, mit Symfony 1.4 umzusetzen. Symfony 1.4 (aktuell 1.4.8) wird bis Ende 2012 unterstützt.

Von Symfony 1.0 ist bekannt dass erste Major-Release-Versionen noch voller Kinderkrankheiten stecken, welche erst nach Jahren zufriedenstellend beseitig werden. Symfony 1.4 hat diese Zeit erfolgreich gemeistert und eine treue Anhängerschaft um sich gebildet. Symfony2.0 steht hier noch am Anfang. Symfony versucht immer einen gewissen Grad an Updatefähig zu gewährleisten, vorausgesetzt die Entwickler halten sich so gut es geht an die vorgegebenen Konventionen. Auch kann man schon von vorn herein versuchen so zu entwickeln das ein evtl. Update später leichter möglich ist, wenn man sich mit den Änderung in der Version 2.0 befasst (s.o.).

Kurzum ein neues Projekt sollte derzeit noch mit Symfony 1.4 umgesetzt werden, jedoch mit technischer Voraussicht auf Symfony2.0.

Symfony2 Benchmark Results:

For the “Product” application, Symfony2 is about:

  • 50% faster than Yii 1.1.1
  • 2.5 times faster than symfony 1.4.2
  • 3 times faster than Zend 1.10
  • 6 times faster than CakePHP 1.2.6

Quelle: http://symfony-reloaded.org/fast

Symfony Nachteile

Symfony hat natürlich auch ein paar Nachteile die Beachtung finden sollten:

  • Größe der Framework-Dateien ohne die Modelklassen: ~30MB.
  • Der Einstieg ist vergleichsweise aufwendig, da erst die Strukturen, Konfigurationsmöglichkeiten und nutzbaren Funktionen gelernt werden müssen.
  • Bei komplexeren Aufgaben kommt man nicht umhin sich mit dem Framework-Kern zu befassen.
  • Nicht dokumentierteÄ nderungen am Kern erschweren Framework-Updates.
  • Wenn kein Zugriff auf die Kommandozeile möglich ist muss ggf. ein Weg gefunden werden die Symfony-Tasks (Unit-Test, Model-Klassen generieren, Cache löschen etc.) auf anderem Wege auszuführen.
  • Symfony ist gerade auf dem Sprung in ein neues Major-Release, welches viele Äderungen mit sich bringt. Es kann sein dass die alte Community evtl. an Aktivität verliert.
  • Viele Vorteile des Frameworks (Admin-, Form- CRUD-Generator etc.) sind Abhängig von einem Datenbank-Modell.
  • Template-Files sind nicht alle in einem Verzeichnis. Grafiker müssen sich ggf. mit der Ordnerstruktur auskennen.
  • YAML-Konfigurations-Files sind sehr empfindlich gegenüber Tippfehlern (Leerzeichen).
  • Updates auf neue Versionen sind oft nicht ganz Problemlos.
  • Ungewolltes überschreiben von Konfigurationsdateien über die Hierarchieebenen.

Ist Symfony das richtige für einen Umstieg?

Für einen kleinen Funktionsumfang wäre Symfony wahrscheinlich zu viel des Guten. Es wäre wohl damit getan sich auf eine Businesslogikstruktur zu einigen und ein Template-System zu integrieren. Doch die meisten Plattformen werden sich ohne Zweifel weiter entwickeln, um den professionellen Ansprüchen der Kunden gerecht zu werden. Hier bietet Symfony bereits die nötige Schablone um solch ein Projekt Modul für Modul zu skalieren bis hin zu höchsten High-Demand-Anforderungen. Der Weg ist durch Symfony bereits geebnet und muss mit unseren Ideen nur noch befahren werden.

Es kam die Frage auf, ob man nicht evtl. nur Teile des Frameworks benutzen könnte. Eigentlich sind nahezu alle Symfony-Features für eine moderne Web-Anwendung essentiell. Trotzdem lassen sich über die tiefgreifenden Konfigurationsfiles die meisten Features einfach abschalten.

Natürlich darf dabei nicht vergessen werden, dass ein Framework auch Probleme mit sich bringen kann, wenn die Umgebung oder die Anforderung an das System zu speziell sind. Spontan stellen sich dann Symfony-Erfahrene die Frage nach der korrekten Funktionsweise des Symfony Caches, des Session-Management, Logging oder das Ausführen von Tasks, was bisher Konsolenzugriffe sowie ein beschreibbares Filessystem voraussetzt. Beantworten lässt sich die Frage mit den symfony-Factories, über die sich nahezu alle Standard-Handler, die für die genannten Funktionen zuständig sind, mit eigenen Lösungen überschreiben oder anpassen lassen.

Symfony ist vielleicht nicht die schnellste Lösung, aber unter den umgesetzten Notwendigkeiten, um die eine Webapplikation nicht herumkommt, unübertroffen. Es lässt sich leicht hardwaretechnisch eine Performancesteigerung erreichen, aber es ist sehr schwer einen neuen Entwickler einem existierenden Projekt hinzuzufügen um es performanter zu machen.

Quellen

Bücher

  • A Gentle Introduction to Symfony 1.4 (ISBN-13: 978-2918390305)
  • More with Symfony 1.3 & 1.4 (ISBN-13: 978-2918390176)

Directory .svn containing working copy admin area is missing

I had this problem because I deleted a conflicted folder out of the repository by using the repo browser.
(It was not possible to delete the folder from my working copy and commit the change).

Now I wanted to add the repaired folder to my working copy which cause the error above.

There are there options to solve this problem:

1. If the folder is a subfolder you can delete the parent folder and make a svn update on everything.
2. If the folder is in the first level you can checkout the whole project again.
3. My solution, which worked very well, was to checkout the whole project to a temp dir, then I copied the first level .svn directory and replaced my working copy .svn folder with this.


Symfony: Propel: Criteria SQL (hibernate sql)

Hi Volks,

today I had a lot of testing with the symfony criteria object. And everyone who knows about the problem to get the raw SQL query out of the criteria object.

There is a toString method, but the result just looks like this:

SELECT FROM media, media_category WHERE media.FEATURED=? AND media.MEDIATYPE IN (?,?) AND 1=1 AND media_category.CID NOT IN (?,?,?,?) AND media.MID=media_category.MID GROUP BY media.MID
Parameters to replace: array (
0 =>
array (
'table' => 'media',
'column' => 'FEATURED',
'value' => true,
),
1 =>
array (
'table' => 'media',
'column' => 'MEDIATYPE',
'value' => 'video',
),
2 =>
array (
'table' => 'media',
'column' => 'MEDIATYPE',
'value' => 'audio',
),
3 =>
array (
'table' => 'media_category',
'column' => 'CID',
'value' => 10,
),
4 =>
array (
'table' => 'media_category',
'column' => 'CID',
'value' => 9,
),
5 =>
array (
'table' => 'media_category',
'column' => 'CID',
'value' => 4,
),
6 =>
array (
'table' => 'media_category',
'column' => 'CID',
'value' => 7,
)
)

And it is very strange to fill the question marks by hand with the related values from the parameters array.

So I wrote a function which does this for me:

function getCriteriaSQL($c, $select = '*')
{
$params = array();
$r = BasePeer::createSelectSql($c, $params);
$o = str_replace('?', '%s', $r);

$ggg = array();
foreach($params AS $e)
{
if(is_integer($e['value']) OR is_bool($e['value']))
{
$ggg[] = $e['value'];
}
else
{
$ggg[] = "'".$e['value']."'";
}
}

$sql = vsprintf($o, $ggg);

$sql = str_replace('SELECT ', 'SELECT '.$select, $sql);

return $sql;
}

I just wanted to share this with you and I appreciate your comments.


Copyright © 1996-2010 iTopiaBlog. All rights reserved.
Jarrah theme by Templates Next | Powered by WordPress