Upload
ippon-technologies
View
1.058
Download
1
Embed Size (px)
DESCRIPTION
Chacun connait les fondamentaux pour développer une API Web, mais quand il s’agit de performance, de capacité, de montée en charge, avez vous toutes les clefs pour mettre en oeuvre un cache efficace ? Le protocole HTTP dispose d’un mécanisme de cache adapté aux architectures distribuées, découvrez ou redécouvrez-le dans cette session et tirez-en profit dans vos API. Le speaker : David développeur, architecte Java EE et directeur du Pôle Conseil d’Ippon Technologies. Passionné de nouvelles technologies, il s’intéresse aux architectures Java alliant simplicité et efficacité, aptes à répondre aux problèmes concrets. Il est aussi un supporter des API Web et du style d’architecture REST.
Citation preview
{theme:”API”, subject:”cache”}
Ippon Technologies © 2014
Présentation
Ippon Technologies © 2014
/ippon/dmartin
David MARTIN… … Ippon Technologies… Directeur du Pôle Conseil et Formation… Développeur depuis … quelques années :)… Intéressé par les API Web, le style d’architecture REST…
Ippon Technologies © 2014
Parlons vrai, parlons cache !
Ippon Technologies © 2014
Let’s start
“La plus performante requête… … est celle qu’on n’a pas à faire”
Un inconnu
Ippon Technologies © 2014
{subject:”cache”}
Parlons un peu de vous…
… vous allez créer une API Web… vous avez créé une API Web
Ippon Technologies © 2014
{subject:”cache”}
Dans le premier cas, vous vous posez quelques questions AVANT → C’est BIEN
Dans le second cas, vous vous posez des questions PENDANT/APRÈS → C’est toujours mieux que de ne pas se poser de question ;) Mais certains de vos choix seront peut être bloquants
Ippon Technologies © 2014
Les constats
Quelques constats…
Les ressources ne partagent pas toutes le même cycle de vie...Certaines changent vraiment très peu...Et pourtant elles peuvent être très demandées…Et induire une forte charge sur le serveur...
Ippon Technologies © 2014
Les constats
On peut identifier des cycles de vie macroscopiques, associés à des types d’entités…
Exemple : Une ressource représentant une cotation boursière évolue à un rythme différent d’une ressource représentant l’entreprise cotée.
Ippon Technologies © 2014
Les constats
Mais deux ressources de même nature peuvent aussi avoir des cycles de vie radicalement éloignés…
Tout le monde n’actualise pas sa page Facebook à la même fréquence...
Ippon Technologies © 2014
Les questions
La question évidente que tout le monde se pose…
… peut on économiser du traitement, de la bande passante, ... sur la lecture des données ?
Ippon Technologies © 2014
Les questions
Ou, dit autrement...
… Comment mettre en place du cache sur mon API ?
Ippon Technologies © 2014
Flashback
Avant toute chose, quelques rappels…
Sur ce qu’est/devrait être une API Web...
Ippon Technologies © 2014
Flashback
Pour cela, commençons par ce que ce n’est pas…
Une API Web n’est pas…… la réincarnation des Web Services SOAP en JSON… un énième hommage au RPC… un simple service qui retourne du JSON… une histoire de jolies URLs
Ippon Technologies © 2014
Flashback
Une API Web est (DOIT ETRE)…… un service orienté ressource et non méthode/action… appelée à être consommée par un client HTTP… construite pour tirer profit du protocole HTTP… autant que possible respectueuse des principes du style d’architecture REST… idéalement construite autour des relations hypermédia
Ippon Technologies © 2014
REST - piqure de rappel
N’est pas API REST qui veut… … Et chaque service - ou API Web - n'atteint pas le même niveau de conformité :
Niveau 0 : RPC like… WS-* style...
Niveau 1 : Notion de ressources
Niveau 2 : Utilisation à bon escient des verbes HTTP
Niveau 3 : Hypertext As The Engine Of Application State
Maturity Model par Leonard Richardson
Ippon Technologies © 2014
So what?
L’API Web doit donc tirer profit du protocole HTTP … … Et pour le cache, qu’en dit la RFC 2616 (Hypertext Transfer Protocol - HTTP/1.1) ?
… Le cache est au coeur du protocole et son usage est plus que conseillé, d’autant qu’il présumé transparent, selon cette définition :
[...]A cache behaves in a "semantically transparent" manner, with respect to a particular response, when its use affects neither the requesting client nor the origin server, except to improve performance.[...]
Ippon Technologies © 2014
Et les caches applicatifs ?
Le protocole HTTP propose donc une solution pour mettre en cache de l’information…
… Mais il existe d’autres solutions de cache (applicatif par exemple) très faciles à intégrer au code d’une API…
… Alors pourquoi se soucier du cache HTTP ?
Ippon Technologies © 2014
Et les caches applicatifs ?
Parce que le cache HTTP va travailler avec des représentations sérialisées, permettant l’économie de la (dé)sérialisation des requêtes et réponses
Et la sérialisation/désérialisation est coûteuse !
Ajoutons à cela qu’un cache HTTP peut être très facilement ajouté et à tout moment, sans impact sur le code de votre API
Ippon Technologies © 2014
Allons-y pour le cache HTTP
Essayons de comprendre maintenant comment cela fonctionne…
… et ce que cela peut apporter à une API Web
Ippon Technologies © 2014
Vocabulaire...
Avant tout chose, entendons nous sur certains termes...
Ippon Technologies © 2014
Caches HTTP : private / shared
Un cache peut être :● privé (non partagé, “non-shared”)
○ Accessible par un seul utilisateur. Le cache de votre navigateur est présumé privé.
● partagé (“shared”)○ Tout autre cache. Ce sera le cas d’un système dédié dans une
infrastructure.
Ippon Technologies © 2014
Caches HTTP : origin server
Notion de serveur d’origine…
… sera le serveur d’où provient à l’origine la donnée potentiellement mise en cache
Ippon Technologies © 2014
Caches HTTP : validator
Notion de validateur…
… sera un élément du protocole utilisé pour déterminer si une entité est bien identique à une autre
Ippon Technologies © 2014
Étudions ce que HTTP propose
Principe général d’un cache : stocker une entité éventuellement associée à une information de validité…
… HTTP propose plusieurs “outils” pour contrôler le comportement du cache…● Time To Live (Expires…)● Cache-Control et ses nombreuses directives...● ETags (ou entity tags)
Ippon Technologies © 2014
Comment gérer le cycle de vie ?
L’approche la plus simple repose sur le Time To Live…… donner au cache une information de péremption concernant la réponse… HTTP 1.1 permet à un serveur d’exprimer cette notion de différentes façons via les headers :● Expires● Cache-Control (max-age)
… Mais un serveur de cache peut aussi gérer cela “seul” en l’absence d’information coté serveur (“Expiration heuristique”)● En se basant sur Last-Modified par exemple
Ippon Technologies © 2014
Zoom sur Expires
Expires (depuis HTTP 1.0)
Permet de spécifier la date, au format RFC 1123, à partir de laquelle la ressource est présumée obsolète
Expires: Tue, 18 Nov 2014 18:15:11 GMT
Ippon Technologies © 2014
Zoom sur Cache-Control
Cache-Control(max-age)
Permet de spécifier en secondes le temps de validité de la ressource retournée (maximum autorisé : 1 année)
Cache-Control: max-age=120
En cas de présence d’Expires et de Cache-Control(max-age), c’est ce dernier qui est retenu
Ippon Technologies © 2014
Zoom sur Cache-Control
Cache-Control...
… C’est aussi beaucoup d’autresdirectives… Pas abordées toutes ici… Assez nébuleuses lors d’unepremière lecture
Ippon Technologies © 2014
Zoom sur Cache-Control
Cache-Control…
… Pour s’y retrouver, Googlepropose ce diagramme assezutile
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#defining-optimal-cache-control-policy
Ippon Technologies © 2014
Retour au cache
Revenons au cache HTTP de façon plus générale...
Ippon Technologies © 2014
Comment ça fonctionne ?
Le fonctionnement est ensuite relativement simple…
… pour toute requête, une correspondance en cache est recherchée (si pas de contre ordre)… si elle est trouvée et qu’elle est “encore fraîche”, elle est retournée,… si elle est trouvée mais “n’est plus très fraîche”, une demande auprès du serveur d’origine est émise,… si elle n’est pas trouvée, elle est demandée au serveur d’origine
Ippon Technologies © 2014
Retour au cache
Tout repose donc sur cette notion de fraîcheur…
… Une entité sera présumée “fraîche” si son âge (pouvant être défini de plusieurs façons) est en conformité par rapport à la règle d’expiration (exprimée ou heuristique)… Au delà, elle est présumée périmée !… Mais peut être ne l’est elle pas ? Comment savoir ?
… En allant vérifier !
Ippon Technologies © 2014
Vérifications optimisées
Les requêtes conditionnelles
Un cache HTTP revalidera une ressource auprès du serveur d’origine en utilisant une requête conditionnelle
Kécécé ?Il s’agit d’une requête qui ne retournera une représentation QUE si nécessaire, et un 304 Not Modified sans corps sinon
Exemple : un GET avec un header If-Modified-Since valorisé avec le Last-Modified de l’entité en cache
Ippon Technologies © 2014
Attention aux limites...
Les limites de la validation avec une date
Revalider une entité avec une date, dont la précision est la seconde, ne garantit pas d’obtenir la donnée plus récente.
Un cache intermédiaire peut avoir récupéré la ressource à T et celle-ci avoir été modifiée sur le serveur d’origine à T+0.1 seconde.Sa ressource est vue comme “fraîche”, et pourtant...
Le validateur utilisé ici est considéré comme “faible”
Ippon Technologies © 2014
Valider “fortement” une entité : ETag
ETag : le validateur fort
Le protocole a donc prévu ce cas…… en permettant de retourner une “clef” identifiant l’état d’une ressource : un tag décrivant l’entité (ie: entity tag ou ETag)Cette valeur peut être alors utilisée pour demander au serveur si cette version de ressource est toujours “fraîche” ou nonGET + (If-(None-)Match) + Etag
Note : la spec HTTP conseille de retourner un ETag, sauf si par exemple le calcul de celui-ci impose un coût trop important
Ippon Technologies © 2014
Allons plus loin encore...
Tout ceci est pas mal, mais il y a mieux…
… Le cache HTTP est aussi prévu pour être invalidé… Les requêtes dites “unsafe” : PUT, DELETE et POST (ou toute autre inconnue) vont marquer les entités du cache comme invalides
Ippon Technologies © 2014
Allons plus loin encore, en images...
GET /people/lucy
Cache Origin
PUT /people/lucy
Cache Origin
Ippon Technologies © 2014
Que peut on tirer de ceci dans une API Web ?
… plus qu’on ne pense !… Voici quelques exemples concrets
Et les API là dedans ?
Plein d’exemples ici
Ippon Technologies © 2014
Et les API là dedans ?
La requête :
POST /people
… va invalider la représentation en cache de /people… mais si combinée avec une réponse du type
[303 - See Other] + Location: /people/lucy ?… ou encore (mieux) avec une réponse :
[20X] + Content-Location: /people/lucy ?
Ceci représente toujours Lucy
Ippon Technologies © 2014
Et les API là dedans ?
La requête :
DELETE /people/lucy
… va invalider la représentation en cache de /people/lucy… mais si combinée avec une réponse du type
[303 - See Other] + Location: /people ?… ou :
[20X] + Content-Location: /people ?
Ippon Technologies © 2014
Tout ceci est valable si...
Attention / Warning / Achtung / 關注
Condition importante pour que cela fonctionne...
… L’URL ne doit pas servir à décrire la modification de l’état d’une ressource :
● POST /people/lucy/smile
● POST /people
Ippon Technologies © 2014
Quid des collections ?
Plusieurs façons d’envisager les collections :● Full hypermédia : la collection est un ensemble de liens vers
les entités● Embarquées : les états des entités sont retournés dans la
réponseLes stratégies de cache devront considérer ces cas en fonction de différents paramètres
Ippon Technologies © 2014
Content Negotiation
Négociation de contenu…
… Une Web API peut proposer de retourner une représentation sous différents formats (JSON, XML, HTML…)Différentes façons le permettent :● GET /resources/res1.json, GET /resources/res1.xml● GET /resources/res1?format=json (xml)● GET /resources/res1 + Accept: application/json (xml)
Ippon Technologies © 2014
Content Negotiation
● GET /resources/res1.json, GET /resources/res1.xml○ L’URL sert de clef pour le cache. Pas de risque de recevoir une
réponse JSON si res1.xml est demandée○ Par contre, l’invalidation ne concernera qu’une seule
représentation...
● GET /resources/res1?format=json (xml)○ Mêmes remarques qu’au dessus
Ippon Technologies © 2014
Content Negotiation
● GET /resources/res1 + Accept: application/json (xml)○ A première vue, c’est mal engagé… une même URL, plusieurs
représentations selon la valeur d’un header…
○ Mais c’est sans compter sur Vary■ Vary est un header positionné sur les réponses■ Il informe les caches des données à considérer pour choisir une
représentation alternative■ Vary: Accept dans notre cas serait donc apprécié!
Encore une fois, tout existe déjà dans la spécification
Ippon Technologies © 2014
Oui mais..., encore...
Mais les choses ne sont jamais simples…
Ippon Technologies © 2014
Un cache, deux caches, n caches...
Et le chemin qu’emprunte une requête peut très bien ne pas être le même que la requête suivante…Ce qui signifie que si une requête “unsafe” a invalidé un ensemble de caches, le prochain GET n’en bénéficiera peut être pas…
Il faut donc apprendre à vivre avec des représentations potentiellement obsolètes
Ippon Technologies © 2014
Accepter l’obsolescence
En utilisant les headers de pré-condition…… Pour rappel If-None-Match, If-Match (et à défaut If-Modified-Since, If-Unmodified-Since)… Sur une action réputée “unsafe”… Permet sur une réponse :
412 Precondition Failed
de réagir en conséquence
No more race condition!
Antisèche
Ippon Technologies © 2014
Accepter l’obsolescence
Demander une ressource au serveur d’origine en by-passant les caches ?
C’est possible !no-cache ou max-age=0 (Cache-Control) permettent de traverser tous les caches jusqu’au serveur d’origine● no-cache : la réponse ne pourra pas être utilisée par les
caches pour les prochaines requêtes● max-age=0 : va aussi permettre de mettre à jour les entités
en cache
Ippon Technologies © 2014
...
2 secondes de pause pour digérer tout ça
Ippon Technologies © 2014
...
1 seconde...
Ippon Technologies © 2014
Subtilités… toujours...
Tout est ok pour activer le cache, n’est-ce pas ?
Ce n’est malheureusement pas si simple…
… Il existe des subtilités à connaître, comme :“Note that Authorization normally prevents a shared cache from saving and returning a response to a previous request if that request included an Authorization header.”
http://pretty-rfc.herokuapp.com/RFC2616#response.cacheability
Ippon Technologies © 2014
Authorization, mon ennemi ?
Pourquoi utiliser Authorization ?
Pour permettre au “user-agent” de s’authentifier auprès du serveur d’origine… … Pour pouvoir restreindre l’accès aux ressources ou à certaines données des ressources… Pour mesurer et contrôler les accès au serveur (quotas, …)
Ippon Technologies © 2014
Authorization, mon ennemi ?
Quelles solutions ?
A étudier selon les cas d’utilisation :● Forcer la mise en cache avec éviction de certaines données
(Cache-Control(no-cache=QQCHOSE))● Ne pas utiliser Authorization sur l’ensemble des ressources
accédées● Utiliser un reverse proxy qui se chargera des contrôles d’
authentification, vérification des quotas, ... et permettra l’utilisation d’un cache pour la requête sortante
Ippon Technologies © 2014
Subtilités… toujours...
Ok pour Authorization, mais si mon API est accédée en HTTPS ?
Alors certaines contraintes vont aussi s’appliquer…
… Les caches partagés ne pourront pas être utilisés… Les caches privés éventuellement
Ippon Technologies © 2014
Et si le client n’est pas un browser
Une API Web peut être consommée par autre chose d’une application AngularJS…
… Heureusement :)… Et si le client est une autre application Java, peut on bénéficier d’un cache privé ?
… Oui! Enfin, si le client HTTP utilisé en propose un :)
Ippon Technologies © 2014
Apache HttpClient Cache
Apache HttpClient dispose d’un mécanisme de cache privé avec 3 implémentations disponibles :● simple/simpliste : stockage dans une LinkedHashMap● A base de EHCache● Avec des morceaux de memcached
Ippon Technologies © 2014
Coté développeur
Tant coté serveur que coté client, la manipulation des headers va donc être importante…
… Coté serveur : Response/CacheControl (JAX-RS), HttpEntity/HttpHeaders (Spring MVC) permettront de travailler les valeurs transmises au client
… Coté client : une requête Ajax aura accès aux headers tout comme Apache HttpClient pour un client Java
Ippon Technologies © 2014
Coté développeur
Quelques règles utiles :● Cache HTTP et cache applicatif ne sont pas exclusifs● ETags : Définissez une stratégie économique pour produire
un ETag
Ippon Technologies © 2014
Un mot pour les Ops
Quels sont les serveurs de cache web ?
Pour n’en citer que quelques uns :● Varnish● Nginx (proxy_cache)● Apache (mod_cache)● Squid● ...
Ippon Technologies © 2014
Un mot pour les Ops
Comment effectuer la rupture SSL ?
Quelques solutions :● Nginx● Apache (mod_ssl)● Pound● Stunnel● ...
Ippon Technologies © 2014
...
Beaucoup de choses ont été dites, la conclusion va s’imposer
Ippon Technologies © 2014
Conclusion !
Ippon Technologies © 2014
Concluons
HTTP 1.1 propose depuis 1999 (...) un ensemble de possibilités très étendues mais trop souvent sous exploitées
Ippon Technologies © 2014
Concluons
Le développeur d’une API Web peut (doit) s’appuyer sur ce potentiel, en connaissant précisément ses limites (*)
(*) : autant les limites du potentiel que celles du développeur ;)
Ippon Technologies © 2014
Concluons
Parcourez la RFC 2616, le contenu est accessible et riche en enseignements
Parcourez aussi les RFC produites depuis pour clarifier la 2616 :● RFC7230 - HTTP/1.1: Message Syntax and Routing● RFC7231 - HTTP/1.1: Semantics and Content● RFC7232 - HTTP/1.1: Conditional Requests● RFC7233 - HTTP/1.1: Range Requests● RFC7234 - HTTP/1.1: Caching● RFC7235 - HTTP/1.1: Authentication
Ippon Technologies © 2014
Concluons
Et surtout…
Ippon Technologies © 2014
{/references}
{
"references": [
{"name": "RFC 2616", "url": "http://pretty-rfc.herokuapp.com/RFC2616"},
{"name": "Google: HTTP Caching", "url": "https://developers.google.com/[...]/http-caching"},
{"name": "Apache HC: HTTP Caching", "url": "http://hc.apache.org/[...]/caching.html"},
{"name": "Key Diff HTTP 1.0 & 1.1", "url": "http://www8.org/w8-papers/[...]/key.html"},
{"name": "Make the web faster", "url": "https://developers.google.com/[...]/caching"},
{"name": "Industry-wide misunderstandings of HTTPS", "url": "securityevaluators.com[...]"},
{"name": "Google", "url": "https://www.google.com"}
]
}
Ippon Technologies © 2014
3-2-1 Contact (& Questions)
Quelques minutes pour vos questions
Pour me contacter :[email protected]@_dmartin_
Envie d’apprendre et de partager ?
Ippon recrute : [email protected]
blog.ippon.frippon.fr atomes.com
@ippontech [email protected]