Quelle méthode de mise en cache est la plus rapide / la plus légère pour Node / Mongo / NginX?

J’ai été chargé de travailler sur un projet pour un client qui possède un site qui, selon lui, recevra 1 à 2 millions de visites par jour. Il possède une firebase database existante de 58 millions d’utilisateurs qui doivent être pré-enregistrés pour la nouvelle marque. La plupart du contenu du site est fourni à partir de données externes fournies par l’API, la plupart des données stockées dans notre configuration Mongo étant des informations de profil et des parameters API enregistrés.

NginX sera sur le port 80 et l’équilibrage de charge sur un cluster de noeuds sur les ports 8000 – 8010.

Ma question est de savoir quoi faire en matière de mise en cache. Je viens d’un contexte LAMP, donc j’ai l’habitude d’écrire des fichiers HTML statiques avec PHP et de les héberger pour minimiser le chargement de MySQL ou d’utiliser Memcached pour les sites nécessitant un niveau de mise en cache plus élevé. Cette configuration est un peu étrangère à moi.

Quel est le plus idéal en termes de temps de réponse minimal et de charge du processeur ?

1: mise en cache au niveau de la page avec NginX

Référence: http://andytson.com/blog/2010/04/page-level-caching-with-nginx/

server { listen 80; servername mysite.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; location / { proxy_pass http://localhost:8080/; proxy_cache anonymous; } # don't cache admin folder, send all requests through the proxy location /admin { proxy_pass http://localhost:8080/; } # handle static files directly. Set their expiry time to max, so they'll # always use the browser cache after first request location ~* (css|js|png|jpe?g|gif|ico)$ { root /var/www/${host}/http; expires max; } } 

2: Redis comme cache

La hash() est la fonction numbers() sur cette page: http://jsperf.com/hashing-ssortingngs

 function hash(str) { var res = 0, len = str.length; for (var i = 0; i < len; i++) { res = res * 31 + str.charCodeAt(i); } return res; } var apiUrl = 'https://www.myexternalapi.com/rest/someparam/someotherparam/?auth=3dfssd6s98d7f09s8df98sdef'; var key = hash(apiUrl).toString(); // 1.8006908172911553e+136 myRedisClient.set(key,theJSONresponse, function(err) {...}); 

3: Node écrit des fichiers JSON

La hash() est la fonction numbers() sur cette page: http://jsperf.com/hashing-ssortingngs

 function hash(str) { var res = 0, len = str.length; for (var i = 0; i < len; i++) { res = res * 31 + str.charCodeAt(i); } return res; } var fs = require('fs'); var apiUrl = 'https://www.myexternalapi.com/rest/someparam/someotherparam/?auth=3dfssd6s98d7f09s8df98sdef'; var key = hash(apiUrl).toString(); // 1.8006908172911553e+136 fs.writeFile('/var/www/_cache/' + key + '.json', theJSONresponse, function(err) {...}); 

4: Vernis devant

J’ai fait des recherches et des tests comme ceux présentés sur ce site, mais je suis toujours prêt à y réfléchir si cela a du sens: http://todsul.com/nginx-varnish

Je ferais une combinaison et utiliserais Redis pour mettre en cache les appels d’API utilisateur de session ayant une durée de vie courte et utiliser Nginx pour mettre en cache les données RESTless et les actifs statiques à long terme. Je n’écrirais pas de fichiers JSON car j’imagine que le système de fichiers IO serait le plus lent et le plus gourmand en CPU parmi les options répertoriées.

  1. La mise en cache au niveau de la page nginx est utile pour la mise en cache du contenu statique. Mais pour le contenu dynamic, ce n’est pas bon. Par exemple, comment invalider le cache si le contenu est modifié en amont?

  2. Redis est parfait pour le stockage de données en mémoire. Mais je n’aime pas l’utiliser comme cache. Avec une quantité de mémoire limitée, je dois constamment craindre de manquer de mémoire. Oui, vous pouvez définir une stratégie pour expirer les clés dans Redis. Mais c’est du travail supplémentaire et toujours pas aussi bon que je veux qu’il soit un fournisseur de cache.

Ne pas avoir d’expérience sur les choix 3 et 4.

Je suis surpris que vous n’incluiez pas ici memcache en option. D’après mon expérience, il est solide en tant que fournisseur de cache. L’une des fonctionnalités de Memcache que redis n’a pas, c’est qu’il ne garantit pas qu’une clé ne sera pas expirée à la date d’expiration spécifiée. Ceci est mauvais pour un magasin de données, mais rend Memcache un candidat idéal pour la mise en cache: vous n’avez pas besoin de vous soucier de l’utilisation de la mémoire que vous avez assignée à memcache. memcache supprimera les clés moins utilisées (le cache moins utilisé) même si le délai d’expiration de ces clés n’est pas encore atteint.

Nginx fournit ce module memcache intégré . C’est solide. Un certain nombre de tutoriels si vous utilisez Google en ligne.

Celui-ci me plait le plus (voir le lien ci-dessous). L’invalidation du cache est simple: par exemple, si une page est mise à jour en amont, supprimez simplement la clé memcache du serveur d’applications en amont. L’auteur a réclamé une augmentation de 4x du temps de réponse. Croyez que c’est assez bon pour votre cas d’utilisation.

http://www.igvita.com/2008/02/11/nginx-and-memcached-a-400-boost/

Quant au vernis, je n’ai pas l’intention de déchiffrer les benchmarks sur le site que vous avez trouvé mais je peux vous dire qu’ils sont terriblement mauvais et n’ont rien de commun avec une véritable implémentation à fort trafic (google pour les optimisations vernis et voir req / s au lieu de 8k).

Nginx est également un choix correct pour un cache de page et avec des access de 1 à 2 millions de fois par jour, vous n’avez pas besoin de performances extrêmes. Alors, allez avec ce que vous sentez plus à l’aise de travailler avec.

Les solutions à deux nœuds sont vraiment un mauvais choix. Un cache de page doit être distinct de votre application dynamic pour fournir à la fois fiabilité et performances.

De plus, redis / memcached vous aidera à dimensionner l’application si vous l’utilisez comme cache d’object ou cache pour des données désérialisées couramment utilisées.