Weitere ähnliche Inhalte Ähnlich wie Web API & Cache, the HTTP way - Ippevent 10 Juin 2014 (20) Web API & Cache, the HTTP way - Ippevent 10 Juin 20143. 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…
5. Ippon Technologies © 2014
Let’s start
“La plus performante requête…
… est celle qu’on n’a pas à faire”
Un inconnu
6. Ippon Technologies © 2014
{subject:”cache”}
Parlons un peu de vous…
… vous allez créer une API Web
… vous avez créé une API Web
7. 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
8. 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...
9. 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.
10. 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...
11. 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 ?
12. Ippon Technologies © 2014
Les questions
Ou, dit autrement...
… Comment mettre en place du cache sur mon API ?
13. Ippon Technologies © 2014
Flashback
Avant toute chose, quelques rappels…
Sur ce qu’est/devrait être une API Web...
14. 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
15. 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
16. 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
17. 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.[...]
18. 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 ?
19. 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
20. 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
21. Ippon Technologies © 2014
Vocabulaire...
Avant tout chose, entendons nous sur certains termes...
22. 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.
23. 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
24. 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
25. 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)
26. 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
27. 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
28. 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
29. Ippon Technologies © 2014
Zoom sur Cache-Control
Cache-Control...
… C’est aussi beaucoup d’autres
directives
… Pas abordées toutes ici
… Assez nébuleuses lors d’une
première lecture
30. Ippon Technologies © 2014
Zoom sur Cache-Control
Cache-Control…
… Pour s’y retrouver, Google
propose ce diagramme assez
utile
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#defining-optimal-cache-control-policy
32. 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
33. 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 !
34. 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
35. 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”
36. 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 non
GET + (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
37. 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
38. Ippon Technologies © 2014
Allons plus loin encore, en images...
GET /people/lucy
Cache Origin
PUT /people/lucy
Cache Origin
39. 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
40. 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
41. 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 ?
42. 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
43. 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éponse
Les stratégies de cache devront considérer ces cas en fonction
de différents paramètres
44. 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)
45. 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
46. 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
48. 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
49. 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
50. 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
53. 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
54. 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, …)
55. 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
56. 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
57. 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 :)
58. 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
59. 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
60. 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
61. 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
● ...
62. Ippon Technologies © 2014
Un mot pour les Ops
Comment effectuer la rupture SSL ?
Quelques solutions :
● Nginx
● Apache (mod_ssl)
● Pound
● Stunnel
● ...
65. Ippon Technologies © 2014
Concluons
HTTP 1.1 propose depuis 1999 (...) un ensemble de possibilités
très étendues mais trop souvent sous exploitées
66. 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 ;)
67. 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
69. 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"}
]
}
70. Ippon Technologies © 2014
3-2-1 Contact (& Questions)
Quelques minutes pour vos questions
Pour me contacter :
dmartin@ippon.fr
@_dmartin_
Envie d’apprendre et de
partager ?
Ippon recrute :
recrutement@ippon.fr