Posts taggés Symfony

Utilisation de cache sur des pages utilisant une session utilisateur avec Symfony 2 et varnish

0

La mise en cache de pages web nécessitant des informations de session (exemple : gestion d’un panier de commande) présente quelques subtilités. Cet article a pour objectif de décrire plusieurs solutions envisageables.

 

Solution 1 :  Page complète en cache et appel Ajax sans cache

 

La page posant un problème de charge serveur est entièrement cachée, sans informations liées à la session utilisateur (sinon GROS problèmes de sécurité).

Cette page contient dans son body HTML un appel Ajax vers une page non cachée et contenant simplement les blocs HTML utilisant des informations liées à la session utilisateur (de préférence sans appel à une base de données ou autre source de données pouvant ralentir la génération de la page).

La réponse de l’appel Ajax doit aussi contenir du code JavaScript permettant de rajouter les blocs HTML dans la page complète.

 

Avantages de cette solution :

  • Une multitude de frameworks JavaScript permettent de mettre en oeuvre facilement cette solution (cf require.js, backbone.js, et bien d’autres…) ;
  • Seuls les blocs utilisant la session ne sont pas cachés, ce qui allège le chargement de données non cachées.

Inconvénients :

  • Cette solution double le nombre d’appels à la plateforme. Toutefois, sur les deux appels, seul l’appel Ajax arrive sur le serveur exécutant PHP, l’autre s’arrêtera au serveur de cache (Varnish) tant que celui-ci est frais ;
  • Avant construction des blocs contenant les informations de session, la page n’affiche pas ces blocs, on peut donc avoir un effet de scintillement de l’interface. Plus problématique, en cas d’erreur du webservice, ces blocs ne seront jamais affichés.

 

Variante possible : utilisation de JSONP + templates

L’appel Ajax peut se faire en JSONP, ce qui permet à la page complète de gérer le templating des blocs HTML en remplacant simplement les valeurs trouvées dans le JSON renvoyé par le webservice.

 

Rappel du JSONP : un webservice est appelé dans une balise <script> placée dans le <head> de la page complète. L’appel à ce webservice contient en paramètre le nom de la fonction javascript qui sera appelée à la fin du chargement de la réponse.

 

Le processus est alors un peu différent :

  1. La page complète est chargée, avec du cache et sans données de session ;
  2. Une fois la page chargée, on lance l’appel JSONP sur un webservice avec un paramètre GET « jsonp » contenant le nom d’une fonction JavaScript existante ;
  3. Le webservice renvoit les données utilisateur au format JSON en paramètres de l’appel à la fonction JavaScript ;
  4. La fonction JavaScript utilise les données du JSON pour compiler les templates des blocs HTML et les ajouter dans le body de la page ;
  5. La page est maintenant complète avec les blocs HTML utilisant les informations de session.

Avantages de cette variante :

  • Templates faciles à maintenir, utilisation possible d’un modèle MVC JavaScript ;
  • Les templates seront mis en cache avec la page complète, ce qui diminue la bande passante nécessaire dans la plupart des cas ;
  • En option, on peut aussi charger les templates par appels Ajax, avec un temps de cache potentiellement plus long. Veiller quand même à ce que le template ET les données soient bien chargés AVANT de compiler le template ;
  • Le webservice ne renvoit que des données, il est donc envisageable de les déporter sur un serveur Node.js pour gagner en performance.

Inconvénients :

  • Demande un traitement supplémentaire côté client : la compilation des templates.

 

Solution 2 : Utilisation des ESI (cache varnish)

 

L’utilisation des ESI permet de cacher des blocs HTML d’une page avec des stratégies différentes. Cela se traduit par l’ajout d’une balise <esi /> dans le code HTML de la page.

Ces balises seront traitées par le serveur de cache (Varnish) de la façon suivante :

  1. Prise en compte des paramètres de cache de la page contenant la balise <esi /> et récupération de son code HTML (soit en cache, soit en rafraichissant le cache) ;
  2. Vérification de la présence de balises <esi /> et prise en compte de leurs paramètres de cache + chargement du contenu du bloc ;
  3. Vérification de la présence de balises <esi /> dans le bloc, etc de façon récursive.

A chaque balise <esi /> doit correspond une URL permettant de rafraichir le bloc.

 

Exemple :

<!DOCTYPE html><html>
    <body>
        <!-- ... some content -->

        <!-- Embed the content of another page here -->
        <esi:include src="http://..." />

        <!-- ... some content -->
    </body></html>

 

Certains frameworks de développement permettent de faciliter l’intégration des ESI. Ainsi dans le cas de Symfony 2 et de Twig, l’intégration des ESI on peut simplement définir un ESI sur une action d’un contrôleur, une route privée sera alors générée par Symfony.

Exemple avec Symfony 2.2 :

{% render '...:news' with {}, {'standalone': true} %}

 

Pour plus d’informations sur l’utlisation des ESI dans Symfony 2, cf http://symfony.com/fr/doc/master/book/http_cache.html#utiliser-esi-avec-symfony2

Pour plus d’informations sur l’utilisation des ESI de Varnish dans un projet Symfony 2 : http://symfony.com/fr/doc/master/cookbook/cache/varnish.html

 

Dans le cas d’un site web n’utilisant pas framework offrant ce type de mécanisme, il faut écrire des routes spécifiques pour chacun des blocs dont le cache est géré par ESI.

 

Avantages de cette solution :

  • Permet non seulement de gérer différemment le cache sur les blocs utilisant des données de session, mais aussi pour n’importe quel type de blocs HTML. (ex : 10 minutes de cache sur la page, 5 minutes sur un bloc, 1 minute sur un sous-bloc ;
  • Solution relativement simple et transparente pour le développeur. Ne demande pas de développement particulier, juste une réorganisation du code pour définir des actions spécifiques dans les contrôleurs.

Inconvénients :

  • Le rafraichissement des blocs <esi /> dont le cache a expiré ralenti le chargement des blocs dont le cache est déjà frais. Donc dans notre cas, le gain peut être faible suivant le temps de chargement du bloc utilisant les données de session ;
  • Plus le nombre de niveaux de balises esi est grand, plus la page complète mettra du temps à être générée par le serveur de cache.

 

Conclusion :

 

Les ESI sont un moyen simple de mettre en place une gestion de cache différenciée par bloc HTML.

Cependant, le gain en performance d’un point de vue utilisateur final ne sera pas forcément flagrant dans le cas de blocs non mis en cache, car ces blocs ralentissent obligatoirement le chargement du reste de la page.

 

Un compromis entre les deux solutions peut être plus intéressant :

  • Utilisation des appels Ajax : pour les blocs utilisant des données non mises en cache ( de préférence, avec utilisation de Node.js + framework MVC JavaScript) ;
  • Utilisation des ESI pour les blocs dont on veut une configuration de cache différente du reste de la page.

 

 

 

Symfony et eZPublish : embarquement immédiat

0

Cet article résume la conférence qui s’est tenue lors du Symfony Live 2013 Paris, relative à la nouvelle version du CMS bien connu eZ Publish.

 

@jeanvoye a commencé sa présentation par poser une question simple : « Qui a déjà travaillé avec eZ 3.x ou eZ 4.x ? » Et à ceux qui ont répondu positivement, il leur a simplement dit « eZ 4.x n’est plus eZ Publish, eZ Publish est désormais eZ 5 ».

Pour sa nouvelle version eZ Systems, éditeur d’eZPublish, a voulu se recentrer sur son cœur de métier à savoir la gestion de contenu et l’expérience utilisateur tout en gardant une architecture scalable et durable.

(Note : Durable comme la version précédente qui est opérationnelle depuis 10 ans)

 

Plusieurs pré-requis étaient indispensables pour la conception de cette nouvelle version comme :

  • une intégration simple d’une API ;
  • un modèle HMVC (Hierarchical Model View Controller), donc pas de logique dans les vues, contrairement aux versions 4.x et antérieures ;
  • un nouveau moteur de template ;
  • des composants découplés.

 

Pour répondre à toutes ces attentes, plusieurs choix ont été étudiés. Parmi ces possibilités figuraient notamment :

  • un framework fait maison
  • Zeta Component
  • Zend Framework
  • Symfony 2

 

Et finalement pour sa version 5 d’eZ Publish, c’est le framework PHP Symfony2 dans sa version intégrale qui a été retenu, ccontrairement à Drupal qui dans sa dernière version (v 8) utilise seulement des composants Symfony 2.

 

Les développeurs d’eZ Publish se sont lancés dans un véritable challenge, car ils ont voulu, entre autres, conserver la même structure que eZ 4.x, mais également le système de templating et le fallback au niveau du routage.

Ce chalenge a été relevé avec succès, car eZ Publish 5 permet une entière rétrocompatibilité avec les versions 4.x en incluant directement ce dernier et en utilisant un système de route dynamique qui fait le passage entre les deux versions en fonction du contexte, la base de donnée restant la même pour les deux. Cette fonctionnalité permet une grande souplesse d’utilisation et d’évolutions pour les sites existants en version 4.x. Les nouveaux développements à apporter sur ces sites pourront alors se faire en eZ 5 et l’interfaçage entre les deux ne posera aucun problème.

 

Cette fusion permet à la fois à SensioLabs de confirmer son statut d’acteur majeur de la communauté PHP Open Source, et également à la communauté Symfony de s’agrandir encore plus (ce fut déjà le cas avec la communauté Drupal).

 

Pour conclure en quelques mots sur cette nouvelle version de eZ Publish , elle se présente comme une application Symfony 2 standard + des bundles (API Rest) + un BackOffice pour gérer le contenu.

D’ailleurs la flexibilité du back-office est conservée, on pourra donc le modifier et y apporter des fonctionnalités/des interfaces spécifiques à chaque projet.

Concernant les versions actuelles et à venir, la version 5.0 est disponible depuis novembre 2012, la version 5.1 est prévue pour mi-mai et la version 5.2 est quant à elle prévue pour novembre 2013.