Maison  >  Article  >  interface Web  >  Utiliser le nœud pour interpréter le contenu du cache http

Utiliser le nœud pour interpréter le contenu du cache http

不言
不言avant
2018-10-29 14:48:251662parcourir

Le contenu de cet article concerne l'utilisation du nœud pour interpréter le contenu du cache http. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

L'utilisation d'un nœud pour fournir des services Web est différente de l'utilisation directe de Tomcat ou d'Apache comme serveurs. Une grande partie du travail doit être effectuée vous-même. Vous devez également choisir votre propre stratégie de mise en cache. Bien qu'il existe des éléments comme koa-static et express.static qui peuvent être utilisés pour gérer les ressources statiques, afin d'être plus à l'aise dans le développement ou la configuration, il est nécessaire de comprendre la mise en cache http. De plus, la mise en cache http, en tant que point clé de l’optimisation front-end, doit également être comprise.

Qu'est-ce que le cache http

La RFC 7234 (https://tools.ietf.org/pdf/rfc7234.pdf) indique que le cache HTTP est le stockage local des messages de réponse et contrôle le stockage des messages dans il. Sous-système de récupération et de suppression.

En termes simples : le protocole http stipule certaines instructions. Les serveurs et les navigateurs qui implémentent le protocole http décident en fonction de ces instructions si et comment stocker la réponse pour une utilisation ultérieure.

Cache http Signification.

Améliorez la vitesse de réponse

Réduisez l'utilisation de la bande passante et économisez du trafic

Réduisez la pression du serveur

Ne spécifiez aucune instruction relative au cache

Dans ce cas, le navigateur ne met pas en cache et fera une requête au serveur à chaque fois. Mais ce qui est étrange, c'est que dans l'implémentation de nginx, dans ce cas, il est toujours mis en cache par le serveur proxy. lors de demandes multiples Pour la même ressource, le serveur proxy ne demande qu'une seule fois au serveur source

Mise en cache forcée

La mise en cache dite forcée consiste à donner le délai d'expiration ou le temps effectif maximum. -âge de la ressource. A ce moment La ressource doit être mise en cache.

Comment rendre une ressource fortement mise en cache

1.expires

Ce champ définit le délai d'expiration de une ressource. Voir un exemple réel :

Utiliser le nœud pour interpréter le contenu du cache http

Vous pouvez voir que ce expires est un GMT moment. la première requête est effectuée, le serveur répond Ajoutez expires pour identifier l'heure d'expiration de la ressource. Le navigateur met en cache cette ressource Lors d'une nouvelle demande, le navigateur comparera l'heure d'expiration de la dernière ressource demandée avec sa propre heure système. . Si l'heure du système est inférieure au délai d'expiration, alors Pour prouver que la ressource n'a pas expiré, utilisez directement la dernière ressource mise en cache sans demander ; sinon, demandez à nouveau et le serveur donnera un nouveau délai d'expiration dans la réponse. 🎜>

const d  = new Date(Date.now() + 5000);
res.writeHead(200, {
    'Content-Type': 'image/png',
    'expires': d.toGMTString()
});
res.end(img);
2.Cache-Control : [public | private ,] max-age=${n}, s-maxage=${m}

Le problème est que cela dépend de l'heure système du client. Une erreur dans l'heure système du client peut provoquer des erreurs de jugement. HTTP1.1 a ajouté expires pour résoudre ce problème. Cette valeur de commande est relativement riche, et les plus courantes sont les suivantes : Cache-Control

  • public/privé : identifie si la ressource peut être mise en cache par le serveur proxy,

    Les ressources de logo peuvent être mises en cache par les serveurs proxy et les navigateurs public Les ressources de logo ne peuvent l'être. mis en cache par les navigateurs, pas par les serveurs proxy. private

  • max-age : Utilisé pour préciser la durée de validité du cache sur le client, en s. requis. S'il ne dépasse pas, le cache peut être utilisé

  • s-maxage : Ceci est pour le serveur proxy. Indique que le temps de cache des ressources sur le serveur proxy ne dépasse pas. cette fois et il n'est pas nécessaire de demander le serveur source, sinon c'est obligatoire

  • no-cache : Avec cette instruction, cela signifie que le cache du navigateur ne sera pas utilisé, et le cache sera toujours négocié. Vous pouvez utiliser

  • no-store : Forcer l'absence de cache, même si le cache est négocié, même s'il y a

    dans la réponse lors du test. , la page n'inclura pas Last-ModifiedIf-Modified-Since

Une instance

. Utiliser le nœud pour interpréter le contenu du cache httpNégocier le cache

Le cache dit négocié signifie que lorsque le client souhaite utiliser la ressource mise en cache, il demande d'abord au serveur si le serveur pense que la ressource n'a pas expiré et peut. continuez à être utilisé, il donnera une réponse 304, et le client continuera à utiliser la ressource d'origine ; sinon, il donnera 200 et répondra dans Le corps ajoute des ressources, et le client utilise de nouvelles ressources

. 1.Last-Modified et If-Modified-Since

Ce mécanisme est que le serveur ajoute

à l'en-tête de réponse. Généralement, c'est l'heure de la dernière modification d'une ressource que le navigateur obtient cette heure. il fait la première requête. Cette heure est placée dans le

de l'en-tête de la requête lors de la requête suivante. Après que le serveur ait reçu cette Last-ModifiedheureIf-Modified-Since, il interroge la fin de la ressource. time If-Modified-Since, si n est donné, une réponse 200 est donnée et m est mis à jour avec la nouvelle valeur. Cette ressource est dans le corps, et le navigateur utilise la nouvelle ressource après l'avoir reçue ; La réponse 304 est donnée, il n'y a aucune donnée dans le corps et le navigateur utilise la dernière ressource mise en cache.m>nLast-Modified2.Etag et If-None-Match

Last-Modified模式存两个问题, 一是它是秒级别的比对, 所以当资源的变化小于一秒时浏览器可能使用错误的资源; 二是资源的最新修改时间变了可能内容并没有变, 但是还是会给出完整响应, 造成浪费. 基于此在HTTP1.1引入了Etag模式.

这个与上面的Last-Modified机制基本相同, 不过不再是比对最后修改时间而是比对资源的标识, 这个Etag一般是基于资源内容生成的标识. 由于Etag是基于内容生成的, 所以当且仅当内容变化才会给出完整响应, 无浪费和错误的问题.

演示第8, 10

如何选择缓存策略

https://tools.ietf.org/pdf/rfc7234.pdf

附录

1.演示代码

const http = require('http');
const fs = require('fs');
let etag = 0;
let tpl = fs.readFileSync('./index.html');
let img = fs.readFileSync('./test.png');
http.createServer((req, res) => {
    etag++; // 我是个假的eTag
    console.log('--->', req.url);
    switch (req.url) {
        // 模板
        case '/index':
            res.writeHead(200, {
                'Content-Type': 'text/html',
                'Cache-Control': 'no-store'
            });
            res.end(tpl);
            break;
        // 1. 不给任何与缓存相关的头, 任何情况下, 既不会被浏览器缓存, 也不会被代理服务缓存
        case '/img/nothing_1':
            res.writeHead(200, {
                'Content-Type': 'image/png'
            });
            res.end(img);
            break;
            
        // 2. 设置了no-cache表明每次要使用缓存资源前需要向服务器确认
        case '/img/cache-control=no-cache_2':
            res.writeHead(200, {
                'Content-Type': 'image/png',
                'cache-control': 'no-cache'
            });
            res.end(img);
            break;

        // 3. 设置max-age表示在浏览器最多缓存的时间
        case '/img/cache-control=max-age_3':
            res.writeHead(200, {
                'Content-Type': 'image/png',
                'cache-control': 'max-age=10'
            });
            res.end(img);
            break;

        // 4. 设置了max-age s-maxage public: public 是说这个资源可以被服务器缓存, 也可以被浏览器缓存, 
        // max-age意思是浏览器的最长缓存时间为n秒, s-maxage表明代理服务器的最长缓存时间为那么多秒
        case '/img/cache-control=max-age_s-maxage_public_4':
            res.writeHead(200, {
                'Content-Type': 'image/png',
                'cache-control': 'public, max-age=10, s-maxage=40'
            });
            res.end(img);
            break;

        // 设置了max-age s-maxage private: private 是说这个资源只能被浏览器缓存, 不能被代理服务器缓存
        // max-age说明了在浏览器最长缓存时间, 这里的s-maxage实际是无效的, 因为不能被代理服务缓存
        case '/img/cache-control=max-age_s-maxage_private_5':
            res.writeHead(200, {
                'Content-Type': 'image/png',
                'cache-control': 'private, max-age=10, s-maxage=40'
            });
            res.end(img);
            break;
        
        // 7. 可以被代理服务器缓存, 确不能被浏览器缓存
        case '/img/cache-control=private_max-age_7':
            res.writeHead(200, {
                'Content-Type': 'image/png',
                'cache-control': 'public, s-maxage=40'
            });
            res.end(img);
            break;
        // 8. 协商缓存
        case '/img/talk_8':
            let stats = fs.statSync('./test.png');
            let mtimeMs = stats.mtimeMs;
            let If_Modified_Since = req.headers['if-modified-since'];
            let oldTime = 0;
            if(If_Modified_Since) {
                const If_Modified_Since_Date = new Date(If_Modified_Since);
                oldTime = If_Modified_Since_Date.getTime();
            }
            
            mtimeMs = Math.floor(mtimeMs / 1000) * 1000;    // 这种方式的精度是秒, 所以毫秒的部分忽略掉
            console.log('mtimeMs', mtimeMs);
            console.log('oldTime', oldTime);
            if(oldTime <p>2.测试用代理服务器nginx配置</p><p>不要问我这是个啥, 我是copy的</p><pre class="brush:php;toolbar:false">worker_processes  8;
  
events {
    worker_connections  65535;
}
  
http {
    include       mime.types;
    default_type  application/octet-stream;
    charset utf-8;
 
    log_format  main  '$http_x_forwarded_for $remote_addr $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_cookie" $host $request_time';
    sendfile       on;
    tcp_nopush     on;
    tcp_nodelay    on;
    keepalive_timeout  65;
    proxy_connect_timeout 500;
    #跟后端服务器连接的超时时间_发起握手等候响应超时时间
    proxy_read_timeout 600;
    #连接成功后_等候后端服务器响应的时间_其实已经进入后端的排队之中等候处理
    proxy_send_timeout 500;
    #后端服务器数据回传时间_就是在规定时间内后端服务器必须传完所有数据
    proxy_buffer_size 128k;
    #代理请求缓存区_这个缓存区间会保存用户的头信息以供Nginx进行规则处理_一般只要能保存下头信息即可  
    proxy_buffers 4 128k;
    #同上 告诉Nginx保存单个用的几个Buffer最大用多大空间
    proxy_busy_buffers_size 256k;
    #如果系统很忙的时候可以申请更大的proxy_buffers 官方推荐*2
    proxy_temp_file_write_size 128k;
    #设置web缓存区名为cache_one,内存缓存空间大小为12000M,自动清除超过15天没有被访问过的缓存数据,硬盘缓存空间大小200g
    #要想开启nginx的缓存功能,需要添加此处的两行内容!
    #设置Web缓存区名称为cache_one,内存缓存空间大小为500M,缓存的数据超过1天没有被访问就自动清除;访问的缓存数据,硬盘缓存空间大小为30G
    proxy_cache_path /usr/local/nginx/proxy_cache_path levels=1:2 keys_zone=cache_one:500m inactive=1d max_size=30g;
 
    #创建缓存的时候可能生成一些临时文件存放的位置
    proxy_temp_path /usr/local/nginx/proxy_temp_path;
 
    fastcgi_connect_timeout 3000;
    fastcgi_send_timeout 3000;
    fastcgi_read_timeout 3000;
    fastcgi_buffer_size 256k;
    fastcgi_buffers 8 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_intercept_errors on;
  
     
    client_header_timeout 600s;
    client_body_timeout 600s;
  
    client_max_body_size 100m;             
    client_body_buffer_size 256k;           
  
    gzip  off;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 9;
    gzip_types       text/plain application/x-javascript text/css application/xml text/javascript;
    gzip_vary on;
  
 
    include vhosts/*.conf;
    server {
        listen       80;
        server_name  localhost;
        location / {
            proxy_pass  http://127.0.0.1:1234;
            proxy_set_header   Host             $http_host;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_redirect off;
            proxy_cache cache_one;
            #此处的cache_one必须于上一步配置的缓存区域名称相同
            proxy_cache_valid 200 304 12h;
            proxy_cache_valid 301 302 1d;
            proxy_cache_valid any 1h;
            #不同的请求设置不同的缓存时效
            proxy_cache_key $uri$is_args$args;
            #生产缓存文件的key,通过4个string变量结合生成
            expires off;
            #加了这个的话会自己修改cache-control, 写成off则不会
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer