ホームページ > 記事 > ウェブフロントエンド > ノードを使用して http キャッシュの内容を解釈する
この記事は、http キャッシュの内容を解釈するためのノードの使用に関するものです。必要な方は参考にしていただければ幸いです。
ノードを使用して Web サービスを提供することは、Tomcat または Apache をサーバーとして直接使用することと同じではありません。 多くの作業は自分で行う必要があります。独自のキャッシュ戦略を選択する必要もありますが、静的リソースの管理に使用できる koa-static や Express.static などがありますが、開発または構成をより快適に行うには、http キャッシュについて理解する必要があります。さらに、フロントエンド最適化の重要なポイントとしての http キャッシュについても理解する必要があります。http キャッシュとは
RFC 7234 (https://tools.ietf.org/pdf/rfc7234.pdf) では、HTTP キャッシュは応答メッセージのローカル ストレージであり、メッセージのストレージを制御すると述べています。取得および削除サブシステム。
平たく言うと、http プロトコルはいくつかの命令を規定しています。http プロトコルを実装するサーバーとブラウザは、これらの命令に基づいて、後で使用するために応答を保存するかどうか、およびその方法を決定します。
http キャッシュ 意味
応答速度の向上
帯域幅の使用量を削減し、トラフィックを節約します
サーバーの負荷を軽減します
キャッシュ関連の命令を指定しないでください
この場合、ブラウザはキャッシュせず、毎回サーバーにリクエストします。しかし、奇妙なのは、この場合、プロキシ サーバーが同じリクエストを複数回キャッシュすることです。
強制キャッシュ
いわゆる強制キャッシュでは、この時点でリソースの有効期限が満了するか、有効期限が切れます。リソースは制限時間内にキャッシュされる必要があります。
リソースを強力にキャッシュする方法
1.expires
このフィールドは、リソースの有効期限を定義します。実際の例:
expires
が GMT
時間であることと、その動作メカニズムがわかります。最初のリクエストを行うときに、サーバーはリソースの有効期限を識別するために応答に expires
を追加します。ブラウザはこのリソースをキャッシュし、再度リクエストするときに、最後のリクエストの有効期限を比較します。要求されたリソースとそれ自体のシステム時間を比較します。システム時間が有効期限よりも短い場合は、最後にキャッシュされたリソースが要求せずに直接使用されます。サーバーは応答で新しい有効期限を返します。
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}
expires
問題は、クライアントのシステム時刻に依存するため、HTTP1.1 で追加された Cache-Control# により、クライアントのシステム時刻エラーが発生する可能性があります。 ## この問題を解決するためのこのコマンドの値は比較的豊富で、一般的なものは次のとおりです:
public 識別リソースはプロキシ サーバーとブラウザの両方でキャッシュできます。
private 識別リソースはプロキシ サーバーでのみキャッシュできますが、ブラウザではキャッシュできません。
Last-Modified が含まれていても、ページには ## が含まれません。 #If-Modified-Since
# ブラウザがリクエストしたとき
##ネゴシエーション キャッシュクライアントが使用したいのは、いわゆるネゴシエーション キャッシュです。リソースをキャッシュする場合、まずサーバーがリソースの有効期限が切れておらず、引き続き使用できるかどうかを確認します。使用されている場合は 304 応答が返され、クライアントは元のリソースを引き続き使用します。それ以外の場合は 200 が返され、そのリソースが応答本文に追加され、クライアントは新しいリソースを使用します。 1.Last-Modified と If-Modified-since
このメカニズムでは、サーバーがIf-Modified-Since
に配置されます。サーバーは、このIf-Modified -Query を最終変更時刻として受け取ります。リソースのsince
timenm
と比較して、
m>nの場合、200の応答を返し、update
Last-Modified は新しい値であり、リソースは本文内にあります。それ以外の場合、ブラウザは 304 応答が返され、最後にキャッシュされたリソースが使用されます。
2.Etag と 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; } } }
以上がノードを使用して http キャッシュの内容を解釈するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。