Les articles de ce blog sont des aides-mémoire et astuces de développement, que j'ai choisi de partager. Ne vous attendez pas à beaucoup de bla bla.
Affichage des articles dont le libellé est Symfony2. Afficher tous les articles
Affichage des articles dont le libellé est Symfony2. Afficher tous les articles
jeudi 18 décembre 2014
lundi 23 décembre 2013
vendredi 7 juin 2013
Setter manuellement la pk d'une entité Doctrine 2
Parfois, pour une une bonne raison, il peut être utile de forcer l'identifiant d'un objet Doctrine2. Celà ne fonctionne pas naturellement, il y a une petite astuce que voici :
lundi 3 juin 2013
Mise en place de Varnish avec Symfony2
Libellés :
Optimisation,
Symfony2
Après une mise en place un peu laborieuse, voici un petit
récapitulatif de ce que j'ai fait pour faire fonctionner Varnish avec
Symfony 2.
La configuration utilisée : Ubuntu 11.10, Varnish 3.0.0-4, Symfony 2.0
Ouvrir le terminal et taper :
Ouvrir et modifier le fichier de configuration de Varnish, par exemple :
Surcharger les méthodes vcl_recv (réception des données), vcl_hash (construction de la clé unique qui correspondra à une entrée de cache donnée) et vcl_fetch :
hash_data(regsub( req.http.Cookie, "^.*?locale=([^;]*);*.*$", "\1" ));
}
permet de gérer un cache par langue, dans le cas où la langue n'est pas spécifiée dans l'URL. Par défaut, Varnish prend pour hash l'URL de la page, donc si votre langue est en session, vous obtiendrez le même contenu pour toutes vos langues. Mettre la locale en cookie, puis ici ajouter sa valeur au hash règle ce problème.
Nous verrons plus bas comment mettre votre locale en cookie.
Après avoir modifié ce fichier, redémarrez Varnish :
Pour cacher un bloc, il faut que celui-ci soit rendu par une action :
La locale sert à gérer le cache par langue, du fait que ce paramètre se retrouve dans l’url interne et donc dans le hash utilisé par Varnish. Si la langue n’est pas encore dans le cookie, le le hash ne contiendra pas la locale ni fr, ni en, mais sera vide. Il est donc mieux de faire :
L’option 'standalone': true va faire que ce bloc deviendra un tag ESI.
Le tag ESI ressemblera à :
Dans l’action qui rend le bloc :
-> Même fonctionnement pour les pages complètes.
Pour ne pas mettre en cache les blocs utilisant par exemple la session, mettre les headers adéquats dans la réponse :
Comme on l'a vu plus haut, si votre locale est dans votre session et non dans l'URL, il faut créer un cookie contenant la locale, au moment où vous changez votre locale ; dans une action changeLocaleAction par exemple.
Lorsque vous vous apprêtez à retourner l'objet Response :
Créer un fichier de test qui fait un CURL sur une URL passée en paramètre GET avec le header “Surrogate-Capability:abc=ESI/1.0”
-> celà permet de voir les balises ESI dans le code source (par exemple en inspectant avec Firebug).
Par exemple web/testvarnish.php
Enfin, vous pouvez tester les performances avec un outil tel que JMeter.
La configuration utilisée : Ubuntu 11.10, Varnish 3.0.0-4, Symfony 2.0
Installation
Ouvrir le terminal et taper :
sudo apt-get install varnish
Configuration de Varnish
Ouvrir et modifier le fichier de configuration de Varnish, par exemple :
sudo vi /etc/varnish/default.vcl
Surcharger les méthodes vcl_recv (réception des données), vcl_hash (construction de la clé unique qui correspondra à une entrée de cache donnée) et vcl_fetch :
sub vcl_recv {
set req.http.Surrogate-Capability = "abc=ESI/1.0";
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
if (req.request != "GET" &&
req.request != "HEAD" &&
req.request != "PUT" &&
req.request != "POST" &&
req.request != "TRACE" &&
req.request != "OPTIONS" &&
req.request != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
if (req.request != "GET" && req.request != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization || req.http.Cookie) {
/* Not cacheable by default */
#return (pass);
}
return (lookup);
}
set req.http.Surrogate-Capability = "abc=ESI/1.0";
permet de dire à Varnish de prendre en charge le langage ESI, qui est
un langage de balisage qui s'insère dans le code HTML, et déclenche des
traitement de construction de la page.set req.http.Surrogate-Capability = "abc=ESI/1.0";
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
if (req.request != "GET" &&
req.request != "HEAD" &&
req.request != "PUT" &&
req.request != "POST" &&
req.request != "TRACE" &&
req.request != "OPTIONS" &&
req.request != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
if (req.request != "GET" && req.request != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization || req.http.Cookie) {
/* Not cacheable by default */
#return (pass);
}
return (lookup);
}
sub vcl_hash {
### these 2 entries are the default ones used for vcl. Below we add our own.
hash_data(req.url);
hash_data(req.http.host);
if( req.http.Cookie ~ "locale" ) {
hash_data(regsub( req.http.Cookie, "^.*?locale=([^;]*);*.*$", "\1" ));
}
return (hash);
}
if( req.http.Cookie ~ "locale" ) {### these 2 entries are the default ones used for vcl. Below we add our own.
hash_data(req.url);
hash_data(req.http.host);
if( req.http.Cookie ~ "locale" ) {
hash_data(regsub( req.http.Cookie, "^.*?locale=([^;]*);*.*$", "\1" ));
}
return (hash);
}
hash_data(regsub( req.http.Cookie, "^.*?locale=([^;]*);*.*$", "\1" ));
}
permet de gérer un cache par langue, dans le cas où la langue n'est pas spécifiée dans l'URL. Par défaut, Varnish prend pour hash l'URL de la page, donc si votre langue est en session, vous obtiendrez le même contenu pour toutes vos langues. Mettre la locale en cookie, puis ici ajouter sa valeur au hash règle ce problème.
Nous verrons plus bas comment mettre votre locale en cookie.
sub vcl_fetch {
if (beresp.http.surrogate-control ~ "ESI/1.0") {
unset beresp.http.surrogate-control;
set beresp.do_esi = true;
}
if (beresp.ttl <= 0s ||
beresp.http.Set-Cookie ||
beresp.http.Vary == "*") {
/*
* Mark as "Hit-For-Pass" for the next 2 minutes
*/
set beresp.ttl = 120 s;
return (hit_for_pass);
}
return (deliver);
}
if (beresp.http.surrogate-control ~ "ESI/1.0") {
unset beresp.http.surrogate-control;
set beresp.do_esi = true;
}
if (beresp.ttl <= 0s ||
beresp.http.Set-Cookie ||
beresp.http.Vary == "*") {
/*
* Mark as "Hit-For-Pass" for the next 2 minutes
*/
set beresp.ttl = 120 s;
return (hit_for_pass);
}
return (deliver);
}
Après avoir modifié ce fichier, redémarrez Varnish :
sudo service varnish restart
Configuration de Symfony2
app/config/config.yml
framework:
templating: { engines: ['twig'] }
session:
default_locale: fr
auto_start: false # Pour ne pas générer le PHPSESSID à chaque page (cache multi user)
esi: true # Pour utiliser les tags ESI dans les templates Twig
templating: { engines: ['twig'] }
session:
default_locale: fr
auto_start: false # Pour ne pas générer le PHPSESSID à chaque page (cache multi user)
esi: true # Pour utiliser les tags ESI dans les templates Twig
app/config/routing.yml
_internal:
resource: "@FrameworkBundle/Resources/config/routing/internal.xml"
prefix: /_internal
-> pour la prise en charge des routes internes de Symfony2 dans les tags ESIresource: "@FrameworkBundle/Resources/config/routing/internal.xml"
prefix: /_internal
web/app.php
//$kernel = new AppCache($kernel);
-> On commente cette ligne pour passer par Varnish et
non plus par le système de cache de Symfony2. (voir s’il y a une
possibilité de gérer ça autrement car ce n'est pas très propre !)Mise en place des blocs et pages cachées dans Symfony2
Pour cacher un bloc, il faut que celui-ci soit rendu par une action :
{% render "NomDeBundle:Test:monAction" with {'locale': app.session.locale}, {'standalone': true} %}
La locale sert à gérer le cache par langue, du fait que ce paramètre se retrouve dans l’url interne et donc dans le hash utilisé par Varnish. Si la langue n’est pas encore dans le cookie, le le hash ne contiendra pas la locale ni fr, ni en, mais sera vide. Il est donc mieux de faire :
{% if app.session.locale %}
{% render "NomDeBundle:Test:monAction" with {'locale': app.session.locale}, {'standalone': true} %}
{% else %}
{% render "NomDeBundle:Test:monAction" with {'locale': app.session.defaultLocale}, {'standalone': true} %}
{% endif %}
{% render "NomDeBundle:Test:monAction" with {'locale': app.session.locale}, {'standalone': true} %}
{% else %}
{% render "NomDeBundle:Test:monAction" with {'locale': app.session.defaultLocale}, {'standalone': true} %}
{% endif %}
L’option 'standalone': true va faire que ce bloc deviendra un tag ESI.
Le tag ESI ressemblera à :
<esi:include src="http://example.com/1.html" onerror="continue"/>
Dans l’action qui rend le bloc :
/**
* Renders the user cart block on the top right of the page
* ESI block
*
* @Extra\Template("NomDeBundle:Test:esi_header_top.html.twig")
*/
public function cartBlockAction() {
$response = new Response();
$response->setContent($this->renderView('NomDeBundle:Test:esi_header_top.html.twig', array()));
$response->setSharedMaxAge(600); # en secondes, donc environ 10 minutes
$response->setPublic();
return $response;
}
-> On ajoute les bons headers à la réponse, où setSharedMaxAge est le temps en secondes de la durée de vie du cache.* Renders the user cart block on the top right of the page
* ESI block
*
* @Extra\Template("NomDeBundle:Test:esi_header_top.html.twig")
*/
public function cartBlockAction() {
$response = new Response();
$response->setContent($this->renderView('NomDeBundle:Test:esi_header_top.html.twig', array()));
$response->setSharedMaxAge(600); # en secondes, donc environ 10 minutes
$response->setPublic();
return $response;
}
-> Même fonctionnement pour les pages complètes.
Pour ne pas mettre en cache les blocs utilisant par exemple la session, mettre les headers adéquats dans la réponse :
$response->setMaxAge(0);
$response->setPrivate();
$response->setPrivate();
Cookie de langue
Comme on l'a vu plus haut, si votre locale est dans votre session et non dans l'URL, il faut créer un cookie contenant la locale, au moment où vous changez votre locale ; dans une action changeLocaleAction par exemple.
Lorsque vous vous apprêtez à retourner l'objet Response :
$response->headers->setCookie(
new Cookie(
'locale',
$votreLocale,
time() + 600));
new Cookie(
'locale',
$votreLocale,
time() + 600));
Pour faire vos tests
Créer un fichier de test qui fait un CURL sur une URL passée en paramètre GET avec le header “Surrogate-Capability:abc=ESI/1.0”
-> celà permet de voir les balises ESI dans le code source (par exemple en inspectant avec Firebug).
Par exemple web/testvarnish.php
<?php
$url = $_GET["url"];
$ret = curl_init($url);
curl_setopt($ret, CURLOPT_HTTPHEADER, array(
'Surrogate-Capability:abc=ESI/1.0'
));
echo curl_exec($ret);
?>
$url = $_GET["url"];
$ret = curl_init($url);
curl_setopt($ret, CURLOPT_HTTPHEADER, array(
'Surrogate-Capability:abc=ESI/1.0'
));
echo curl_exec($ret);
?>
Enfin, vous pouvez tester les performances avec un outil tel que JMeter.
Inscription à :
Articles (Atom)