Cocktailand – La stack technique


A la vue de cet article, on me dira surement que la stack technique du site Cocktailand est overkill.

Ma réponse est simple: « Ouaip carrément !« 

Au-delà du plaisir de travailler sur la thématique des cocktails, je travaille sur ce projet aussi pour me faire plaisir techniquement et pour tester des technologies ou des services en mode SAS.

Comme j’ai toujours la flemme de documenter mes sides projects, cet article fera office de documentation « technique ».

Je vais donc découper cet article en trois parties:

  • L’hébergement
  • L’application
  • Les services SAS utilisés

L’hébergement

Scaleway

Depuis la beta de scaleway, filiale de Online, je prends tous mes serveurs persos chez eux. Ils sont à la fois fiables, efficaces et abordables. Il n’y a pas de frais d’installation et on peut libérer un serveur à tout moment. Pour Cocktailand, j’ai pris deux serveurs pour démarrer, un pour la prod et un pour les backups qui n’a pas d’accès à Internet (ni entrant ni sortant). Pour toute la partie métrique graphite/ grafana, j’ai pluggué le site sur mon infra existante.

Le serveur qui héberge le site est un START1-S. Ce n’est pas une bête de course, mais au besoin je passerai à la gamme au-dessus.

Cloudflare

Cloudflare est un gestionnaire de DNS en ligne qui a pour particularité d’avoir un temps de propagation proche de 0. Dans son offre de base, qui est gratuite, il permet de gérer plusieurs noms de domaine, il autorise les wildcards dans les sous-domaines, mais il propose aussi tout un tas d’autres fonctionnalités intéressantes. En effet, dans l’offre gratuite, il propose:

  • Une protection DDOS
  • Une optimisation des assets à la volée
  • Une redirection http vers https automatique
  • Une modification des urls des assets des pages de http vers https (un garde-fou sympa si on est full https)
  • Une redirection automatique vers un site mobile (s’il est différent)
  • La possibilité de bannir des ips (manuellement ou via une API)

Pour ma part, je l’utilise depuis longtemps et je n’ai jamais eu à me plaindre du moindre dysfonctionnement.

Docker compose

La stack du site est entièrement gérée avec docker.

Chaque brique de la partie docker (varnish, nginx, phpfpm ) peut scaller horizontalement.

Pour le moment, le serveur MySQL ainsi que les images ne sont pas scallables. Je travaillerai sur les deux points si jamais le besoin s’en fait sentir. Normalement, avec l’utilisation intensive de varnish qui est faite, la base de données n’est pas énormément sollicitée.

L’application

Le site est développé avec le framework Symfony. J’ai choisi SF pour sa stabilité, sa fiabilité, mais aussi car j’ai l’habitude de travailler avec au quotidien. Je sais que, bien utilisé, il est capable de tenir la charge.

Le site fait un usage assez intensif des ESI afin de permettre une gestion du cache http assez fine. Quasiment chaque bloc de la home est un ESI. Il est par exemple possible d’avoir un temps de cache de quelques heures pour le cocktail du jour et un cache d’une journée sur le top des cocktails les plus consultés.

Images

La problématique n’est pas de trouver des recettes de cocktails, mais de trouver des images libres de droits. Je n’ai malheureusement pas eu le temps de confectionner par moi-même l’ensemble des cocktails présents sur le site.

Voici donc une liste non exhaustive des sites sur lesquels je vais chercher des images quand je n’en ai pas:

Les services SAS utilisés

Comme je l’ai dit plus tôt, Cocktailand a aussi pour but de tester des technologies ou des services en SAS.

Algolia

Surnommé le « Google des apps », Algolia est un service externe de moteur de recherche. Il remplace le bon vieux cluster ElasticSearch que j’aurais pu mettre sur mon serveur.

En plus d’être extrêmement performant, algolia a un service client au top.

L’offre gratuite me permet largement de faire tourner mon moteur de recherche sans restriction et avec des temps de réponse aux alentours de 50ms. La seule contrepartie demandée par algolia est de préciser que la recherche est fournie par eux en dessous des résultats.

Très franchement, je suis agréablement surpris par cette techno.

Logz.io

Logz est un agrégateur de logs en mode SAS. Comme je n’ai rien de critique dans les logs, je me suis permis de les externaliser. On retrouve une bonne vieille stack ELK.

Pour envoyer les logs, il m’a suffi d’ajouter leur container docker rsyslog dans ma stack docker-compose. Une fois les bonnes variables d’environnements mises en place les logs remontent chez eux en quasi temps réel.

Au-delà de la simple consultation et recherche dans les logs, ils proposent un outil d’alerting. Il est par exemple possible d’envoyer un mail quand un grand nombre d’exceptions ou de fatales sont remontées.

Coût de la plateforme

Comme le site est encore récent et qu’il ne génère aucun revenu, j’ai fait le maximum pour réduire les coûts.

Voici un état des lieux des dépenses engendrées par Cocktailand.

[table id=1 /]

Cocktailand – Monitorer les performances d’un site web

Les outils

Monitorer les performances WEB d’un site web est vraiment indispensable, mais ce n’est pas simple de le faire gratuitement. Il existe des outils en ligne comme SpeedCurve mais c’est relativement cher.

L’idée ici est d’avoir un suivi, certes plus simple, mais de façon gratuite. Il se trouve que j’ai déjà une stack graphite/grafana qui tourne en production. Si ce n’est pas votre cas et que vous avez un serveur avec docker qui tourne dessus vous pouvez toujours démarrer un container avec l’image docker-grafana-graphite pour tester la suite de cet article. Une fois que votre graphite est en ligne on va pouvoir commencer à pousser des metrics dedans. Un outil est très connu pour obtenir des metrics de performance sur un site web. Webpagetest, dont j’ai déjà parlé dans un billet précédent sur la mise en place de varnish et des ESIs. Il se trouve que webpagetest fournie une api.

Pour obtenir une clef d’api il faut en faire la demande sur le site de WebPageTest.

Vous recevrez votre clef par email automatiquement sous quelques minutes.

La mise en place

Il ne reste plus qu’a faire le lien entre les retours de l’API de webpagetest et notre graphite. J’ai choisi de faire un petit script en node js, mais vous pouvez le faire avec ce que vous voulez.

Installer les dépendances

npm install statsd-client webpagetest –save

Le script

Très claireiment c’est pas un script optimisé ni prévu pour monitorer plusieurs pages d’un site. Maintenant si vous avez besoin d’étendre son scope ce ne sera pas trop difficile.

Il y a quelques placeholder dans le script à remplacer par vos valeurs:

  • NOM_DU_SITE_OU_DE_LA_PAGE: Le nom de votre site en snake case (ex: cocktailand_fr)
  • VOTRE_URL: L’url de la page à monitorer (ex https://cocktailand.fr)
  • VOTRE_HOST_GRAPHITE: L’ip ou le hostname de votre graphite
  • VOTRE_API_KEY: La clef d’api que WebPageTest vous a donnée
const WebPageTest = require('webpagetest');
const http = require('http');
const SDC = require('statsd-client'),
sdc = new SDC({
prefix: '<NOM_DU_SITE_OU_DE_LA_PAGE>.webpagetest',
host: '<VOTRE_HOST_GRAPHITE>',
port: 8125
});
const wpt = new WebPageTest('www.webpagetest.org', '<VOTRE_API_KEY>');
wpt.runTest('<VOTRE_URL>', {location: 'ec2-eu-west-1:Chrome'}, (err, data) => {
if (err) {
console.error(err);
return;
}
let jsonUrl = data.data.jsonUrl;
let iterationNumber = 0;
let stop = setInterval(function () {
// 20 mins max
if (iterationNumber > 600) {
clearInterval(stop);
return;
}
iterationNumber ++;
http.get(jsonUrl, (resp) => {
let rawData = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
rawData += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
let response = JSON.parse(rawData);
if (response.statusCode === 200) {
clearInterval(stop);
['firstView', 'repeatView'].forEach((key) => {
sdc.gauge(key + '.first_paint', response.data.median[key].firstPaint);
sdc.gauge(key + '.fully_loaded', response.data.median[key].fullyLoaded);
sdc.gauge(key + '.bytes_out', response.data.median[key].bytesOut);
sdc.gauge(key + '.image_total', response.data.median[key].image_total);
sdc.gauge(key + '.load_time', response.data.median[key].loadTime);
sdc.gauge(key + '.speed_index', response.data.median[key].SpeedIndex);
sdc.gauge(key + '.cached', response.data.median[key].cached);
sdc.gauge(key + '.dom_interactive', response.data.median[key].domInteractive);
sdc.gauge(key + '.nb_domains', Object.keys(response.data.median[key].domains).length);
sdc.gauge(key + '.resources.html.size', response.data.median[key].breakdown.html.bytes);
sdc.gauge(key + '.resources.html.nb', response.data.median[key].breakdown.html.requests);
sdc.gauge(key + '.resources.css.size', response.data.median[key].breakdown.css.bytes);
sdc.gauge(key + '.resources.css.nb', response.data.median[key].breakdown.css.requests);
sdc.gauge(key + '.resources.js.size', response.data.median[key].breakdown.js.bytes);
sdc.gauge(key + '.resources.js.nb', response.data.median[key].breakdown.js.requests);
sdc.gauge(key + '.resources.image.size', response.data.median[key].breakdown.image.bytes);
sdc.gauge(key + '.resources.image.nb', response.data.median[key].breakdown.image.requests);
});
}
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}, 2000);
});

Cronner le script

Je fait tourner le script toutes les heures.

0 * * * * node webPageTest.js

De cette manière je peux analyser le comportement du site sur une journée complète et éliminer les fausses alertes.

Il est en effet possible d’avoir des résultats qui varient en fonctions de plusieurs facteurs extérieur:

  • La saturation du réseau de webPageTest
  • Un agent de webpagetest qui est plus lent qu’un autre
  • Des publicités mal optimisées de la part d’un partenaire

Il ne faut pas s’inquiéter si un résultat est moins bon qu’un autre.

Le but ici est d’analyser une tendance.

Faire un beau dashboard

Maintenant que vous avez toutes vos informations dans votre graphite on peut commencer à grapher ce qui nous intéresse.

Voici par exemple mon dashboard:

Pour ma part je surveille principalement les temps de réponse et le cache avec mon dashboard, mais en fonction des objectifs que l’on se donne on peut axer les graphiques sur d’autres KPIs.

Conclusion

J’ai un suivi des performances. Si grafana est à jour (ce qui n’est pas mon cas) il est même possible d’envoyer des mails d’alertes quand on dépasse une limite fixée.

Après plusieurs semaines d’exploitation je me rends compte que le site en lui-même est stable et avec des performances prévisibles, mais que les grandes inconnues sont les publicités. Une mauvaise pub sur le site peut anéantir tout le travail fait en amont sur les performances.