Serveur d'impression

KissCache, cachant le baiser – Serveur d’impression

Le 10 avril 2020 - 6 minutes de lecture

Résumé

présentation

Récemment, une dépêche a présenté "kisscache", un serveur de cache HTTP (S). Particularité, il ne lance qu'un seul téléchargement simultané pour la même ressource.

efficacité du réseau

Cette fonctionnalité permet, si plusieurs clients viennent de télécharger la même ressource, avant qu'elle ne soit mise en cache, de ne pas envoyer plusieurs fois la même requête au serveur et donc d'économiser de la bande passante côté client et serveur. Au final, tous les clients seront servis plus rapidement.

Cache HTTPS

De plus, l'outil propose de résoudre le problème de mise en cache des ressources proposées en HTTPS. En effet, un cache server agit comme un "homme au milieu" et est donc difficilement compatible avec un transport sécurisé dont le but est, entre autres, de ne pas permettre la modification de la réponse du serveur sans que le client ne le détecte. Une solution courante – en particulier dans les entreprises pour inspecter le flux client-serveur, plus que pour la mise en cache – consiste à usurper le certificat du serveur, en le remplaçant par un certificat provenant d'une autorité de confiance interne déployée sur les clients des machines. Il faut encore mener à bien ce déploiement.

BAISER?

L'outil est présenté comme suivant le principe KISS. Il est vrai que le nombre de fonctionnalités est limité et que la quantité de code est petite, environ mille lignes de python. Cependant, les dépendances d'exploitation sont importantes: django pour l'API, postgres pour la base de données, céleri pour le traitement asynchrone, redis pour le bus de données, docker pour l'infrastructure. La réécriture d'URL rend son utilisation difficile.

une analyse

Cache HTTPS

La solution proposée consiste à réécrire les URL de toutes les ressources demandées. Il est donc beaucoup plus intrusif et non standard que d'utiliser un proxy conventionnel. Un proxy demande des variables d'environnement, des paramètres de ligne de commande ou une modification du fichier de configuration. Un proxy transparent demande une configuration au réseau local ou au routeur. Concrètement, aucun gestionnaire de progiciel (apt, pip, etc.) ne permet la réécriture d'URL. Et par conséquent, vous devez disposer d'outils spécialement écrits pour être compatible avec kisscache.

BAISER

De toute évidence, la gestion d'un cache HTTP (S) n'est pas ne pas Facile. Le protocole HTTP est compliqué, avec de nombreux scénarios, notamment sur la gestion du cycle de vie des ressources, influencés par de nombreux en-têtes. L'outil kisscache ne le gère pas vraiment.
Quelles autres pistes pouvons-nous suivre?

nginx

Nginx n'est pas un logiciel simple. Mais sa mise en œuvre l'est. Avec un fichier de configuration relativement court – moins de vingt lignes – il gère correctement un cache HTTP (S) avec les mêmes fonctionnalités que celles attendues pour kisscache:

                serveur 
écouter 3128;

expire max;
proxy_cache on;
proxy_cache_path / var / cache / proxy-nginx inactive = 1w; # une semaine
proxy_cache_key "$ schéma: // $ host $ request_uri";
proxy_pass $ schéma: // $ host $ request_uri;
proxy_set_header Host $ http_host;
proxy_ignore_headers "Set-Cookie";

proxy_ignore_client_abort on;
proxy_cache_lock activé;
proxy_cache_lock_age 10m;
proxy_cache_valid 200 301 1w; # une semaine
proxy_cache_valid any 1m;
erreur proxy_cache_use_stale;

La directive "proxy_cache_lock" permet de n'avoir qu'un seul client à la fois téléchargeant une ressource. La directive "proxy_ignore_client_abort" permet de terminer le téléchargement même si le client interrompt la connexion. La directive "inactive = 1w" permet de nettoyer les ressources non consultées depuis un certain temps.

Python asynchrone

S'il s'agit d'écrire un serveur en python qui cache les URL qui lui sont soumises, une approche simple consiste à connecter deux bibliothèques logicielles entre elles: un serveur HTTP et un client HTTP. Et pour plus d'efficacité, allez voir le côté des capacités AsyncIO de Python. En collant l'exemple de serveur et l'exemple de client de la page d'accueil aiohttp, nous arrivons rapidement à un prototype fonctionnel. Nous ajoutons entre les deux une gestion de fichiers (cache) et un mécanisme pour empêcher les téléchargements multiples et nous obtenons les quarante lignes de code suivantes:

importer asyncio
depuis le site d'import aiohttp, ClientSession
de hashlib import md5
importer os
depuis aiofile import AIOFile

D = 

async def dl_and_cache (url, dirname, basename):
async avec ClientSession () en tant que session:
async avec session.get (url) comme réponse:
content = attendre réponse.read ()
os.makedirs (dirname, exist_ok = True)
path = dirname + "/" + basename
asynchrone avec AIOFile (chemin, & # 39; wb & # 39;) comme afp:
attendre afp.write (contenu)


Poignée async def (demande):
url = request.match_info.get (& # 39; url & # 39;)
imprimer (url)
h = md5 (octets (url, "ascii")). hexdigest ()
dirname = ".cache /" + h[0:2]+ "/" + h[2:4]
    nom de base = h[4:]
    path = dirname + "/" + basename
sinon os.path.exists (chemin):
# si le téléchargeur est marqué, attendez-le
si l'URL en D:
tandis que l'URL en D:
attendre asyncio.sleep (1)
# else, marquer comme téléchargement et commencer le téléchargement
autre:
ré[url] = Aucun
# utiliser le bouclier pour empêcher l'annulation de la déconnexion du client
attendre asyncio.shield (dl_and_cache (url, dirname, basename))
del D[url]
    retourne web.FileResponse (chemin)


si __name__ == & # 39; __ main __ & # 39 ;:
app = web.Application ()
app.add_routes ([web.get('/url', handle)]) # l'url doit être encodée en url
web.run_app (application)

Les dépendances sont résolues avec un pip install aiohttp[speedups] aiofile.
A tester avec wget http://0.0.0.0:8080/$(urlencode & # 39; http: //dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz') par exemple.

Pour atteindre le niveau fonctionnel de l'outil proposé, il faudrait ajouter la gestion du TTL et la suppression des ressources non utilisées depuis un certain temps. Cela devrait être possible en restant sous les cent lignes de code.
Ensuite, PyInstaller regroupe tout dans un binaire autoportant – c'est-à-dire: incorporant l'interpréteur python et les dépendances – de moins de 11 Mo.

Je vous remercie

Je remercie l'auteur de son envoi. Cela m'a permis de réfléchir au problème de la mise en cache des ressources proposé dans https et qui me pose également des problèmes pour les tâches de construction de logiciels, de regarder dans aiohttp qui est une très bonne surprise, de revenir sur nginx qui est définitivement un outil très puissant, pour voir une bonne intégration de django + celery qui est un bon modèle pour construire des API pour l'automatisation de l'infrastructure.

Commentaires

Laisser un commentaire

Votre commentaire sera révisé par les administrateurs si besoin.