真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

怎么理解緩存

本篇內(nèi)容介紹了“怎么理解緩存”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

創(chuàng)新互聯(lián)公司不只是一家網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司;我們對營銷、技術(shù)、服務(wù)都有自己獨特見解,公司采取“創(chuàng)意+綜合+營銷”一體化的方式為您提供更專業(yè)的服務(wù)!我們經(jīng)歷的每一步也許不一定是最完美的,但每一步都有值得深思的意義。我們珍視每一份信任,關(guān)注我們的網(wǎng)站制作、做網(wǎng)站質(zhì)量和服務(wù)品質(zhì),在得到用戶滿意的同時,也能得到同行業(yè)的專業(yè)認(rèn)可,能夠為行業(yè)創(chuàng)新發(fā)展助力。未來將繼續(xù)專注于技術(shù)創(chuàng)新,服務(wù)升級,滿足企業(yè)一站式營銷型網(wǎng)站建設(shè)需求,讓再小的成都品牌網(wǎng)站建設(shè)也能產(chǎn)生價值!

瀏覽器緩存

瀏覽器緩存是指當(dāng)我們?nèi)ピL問一個網(wǎng)站或者Http服務(wù)的時候,服務(wù)器可以設(shè)置Http的響應(yīng)頭信息,其中如果設(shè)置緩存相關(guān)的頭信息,那么瀏覽器就會緩存這些數(shù)據(jù),下次再訪問這些數(shù)據(jù)的時候就直接從瀏覽器緩存中獲取或者是只需要去服務(wù)器中校驗下緩存時候有效,可以減少瀏覽器與服務(wù)器之間的網(wǎng)絡(luò)時間的開銷以及節(jié)省帶寬。

> Htpp相關(guān)的知識,歡迎去參觀 《面試篇》Http協(xié)議

Cache-Control

該命令是通用首部字段(請求首部和響應(yīng)首部都可以使用),用于控制緩存的工作機制,該命令參數(shù)稍多,常用的參數(shù):

  • no-cache: 表示不需要緩存該資源

  • max-age(秒): 緩存的最大有效時間,當(dāng)max-age=0時,表示不需要緩存

Expires

控制資源失效的日期,當(dāng)瀏覽器接受到Expires之后,瀏覽器都會使用本地的緩存,在過期日期之后才會向務(wù)器發(fā)送請求;如果服務(wù)器同時在響應(yīng)頭中也指定了Cache-Controlmax-age指令時,瀏覽器會優(yōu)先處理max-age。 如果服務(wù)器不想要讓瀏覽器對資源緩存,可以把Expires和首部字段Date設(shè)置相同的值

Last-Modified / If-Modified-Since

Last-Modified

怎么理解緩存

Last-Modified 用于指明資源最終被修改的時間。配合If-Modified-Since一起使用可以通過時間對緩存是否有效進行校驗;后面實戰(zhàn)會使用到這種方式。

If-Modified-Since

怎么理解緩存

怎么理解緩存

如果請求頭中If-Modified-Since的日期早于請求資源的更新日期,那么服務(wù)會進行處理,返回最新的資源;如果If-Modified-Since指定的日期之后請求的資源都未更新過,那么服務(wù)不會處理請求并返回304 Mot Modified的響應(yīng),表示緩存的文件有效可以繼續(xù)使用。

實戰(zhàn)事例

使用SpringMVC做緩存的測試代碼:

@ResponseBody
@RequestMapping("/http/cache")
public ResponseEntity cache(@RequestHeader(value = "If-Modified-Since", required = false)
                                            String ifModifiedSinceStr) throws ParseException {

    DateFormat dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
    Date ifModifiedSince = dateFormat.parse(ifModifiedSinceStr);

    long lastModifiedDate = getLastModifiedDate(ifModifiedSince);//獲取文檔最后更新時間
    long now = System.currentTimeMillis();
    int maxAge = 30; //數(shù)據(jù)在瀏覽器端緩存30秒

    //判斷文檔是否被修改過
    if (Objects.nonNull(ifModifiedSince) && ifModifiedSince.getTime() == lastModifiedDate) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Date", dateFormat.format(new Date(now))); //設(shè)置當(dāng)前時間
        headers.add("Expires", dateFormat.format(new Date(now + maxAge * 1000))); //設(shè)置過期時間
        headers.add("Cache-Control", "max-age=" + maxAge);
        return new ResponseEntity<>(headers, HttpStatus.NOT_MODIFIED);
    }

    //文檔已經(jīng)被修改過
    HttpHeaders headers = new HttpHeaders();
    headers.add("Date", dateFormat.format(new Date(now))); //設(shè)置當(dāng)前時間
    headers.add("Last-Modified", dateFormat.format(new Date(lastModifiedDate))); //設(shè)置最近被修改的日期
    headers.add("Expires", dateFormat.format(new Date(now + maxAge * 1000))); //設(shè)置過期時間
    headers.add("Cache-Control", "max-age=" + maxAge);

    String responseBody = JSON.toJSONString(ImmutableMap.of("website", "https://silently9527.cn"));
    return new ResponseEntity<>(responseBody, headers, HttpStatus.OK);

}

//獲取文檔的最后更新時間,方便測試,每15秒換一次;去掉毫秒值
private long getLastModifiedDate(Date ifModifiedSince) {
    long now = System.currentTimeMillis();

    if (Objects.isNull(ifModifiedSince)) {
        return now;
    }

    long seconds = (now - ifModifiedSince.getTime()) / 1000;
    if (seconds > 15) {
        return now;
    }
    return ifModifiedSince.getTime();
}
  1. 當(dāng)?shù)谝淮卧L問http://localhost:8080/http/cache的時候,我們可以看到如下的響應(yīng)頭信息:

怎么理解緩存

前面我們已提到了Cache-Control的優(yōu)先級高于Expires,實際的項目中我們可以同時使用,或者只使用Cache-Control。Expires的值通常情況下都是系統(tǒng)當(dāng)前時間+緩存過期時間

  1. 當(dāng)我們在15秒之內(nèi)再次訪問http://localhost:8080/http/cache會看到如下的請求頭:

怎么理解緩存

此時發(fā)送到服務(wù)器端的頭信息If-Modified-Since就是上次請求服務(wù)器返回的Last-Modified,瀏覽器會拿這個時間去和服務(wù)器校驗內(nèi)容是否發(fā)送了變化,由于我們后臺程序在15秒之內(nèi)都表示沒有修改過內(nèi)容,所以得到了如下的響應(yīng)頭信息

怎么理解緩存

響應(yīng)的狀態(tài)碼304,表示服務(wù)器告訴瀏覽器,你的緩存是有效的可以繼續(xù)使用。

If-None-Match / ETag

If-None-Match

怎么理解緩存

請求首部字段If-None-Match傳輸給服務(wù)器的值是服務(wù)器返回的ETag值,只有當(dāng)服務(wù)器上請求資源的ETag值與If-None-Match不一致時,服務(wù)器才去處理該請求。

ETag

響應(yīng)首部字段ETag能夠告知客服端響應(yīng)實體的標(biāo)識,它是一種可將資源以字符串的形式做唯一標(biāo)識的方式。服務(wù)器可以為每份資源指定一個ETag值。當(dāng)資源被更新時,ETag的值也會被更新。通常生成ETag值的算法使用的是md5。

  • 強ETag值:不論實體發(fā)生了多么細微的變化都會改變其值

  • 弱ETag值:只用于提示資源是否相同,只有當(dāng)資源發(fā)送了根本上的變化,ETag才會被改變。使用弱ETag值需要在前面添加W/

ETag: W/"etag-xxxx"

通常建議選擇弱ETag值,因為大多數(shù)時候我們都會在代理層開啟gzip壓縮,弱ETag可以驗證壓縮和不壓縮的實體,而強ETag值要求響應(yīng)實體字節(jié)必須完全一致。

實戰(zhàn)事例
@ResponseBody
@RequestMapping("/http/etag")
public ResponseEntity etag(@RequestHeader(value = "If-None-Match", required = false)
                                           String ifNoneMatch) throws ParseException {
    long now = System.currentTimeMillis();
    int maxAge = 30; //數(shù)據(jù)在瀏覽器端緩存30秒

    String responseBody = JSON.toJSONString(ImmutableMap.of("website", "https://silently9527.cn"));
    String etag = "W/\"" + MD5Encoder.encode(responseBody.getBytes()) + "\""; //弱ETag值

    if (etag.equals(ifNoneMatch)) {
        return new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
    }

    DateFormat dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
    HttpHeaders headers = new HttpHeaders();
    headers.add("ETag", etag);
    headers.add("Date", dateFormat.format(new Date(now))); //設(shè)置當(dāng)前時間
    headers.add("Cache-Control", "max-age=" + maxAge);

    return new ResponseEntity<>(responseBody, headers, HttpStatus.OK);
}

ETag是用于發(fā)送到服務(wù)器端進行內(nèi)容變更驗證的,第一次請求http://localhost:8080/http/etag,獲取到的響應(yīng)頭信息:

怎么理解緩存

在30秒之內(nèi),我們再次刷新頁面,可以看到如下的請求頭信息:

怎么理解緩存

這里的If-None-Match就是上一次請求服務(wù)返回的ETag值,服務(wù)器校驗If-None-Match值與ETag值相等,所以返回了304告訴瀏覽器緩存可以用。

怎么理解緩存

ETag與Last-Modified兩者應(yīng)該如何選擇?

通過上面的兩個事例我們可以看出ETag需要服務(wù)器先查詢出需要響應(yīng)的內(nèi)容,然后計算出ETag值,再與瀏覽器請求頭中If-None-Match來比較覺得是否需要返回數(shù)據(jù),對于服務(wù)器來說僅僅是節(jié)省了帶寬,原本應(yīng)該服務(wù)器調(diào)用后端服務(wù)查詢的信息依然沒有被省掉;而Last-Modified通過時間的比較,如果內(nèi)容沒有更新,服務(wù)器不需要調(diào)用后端服務(wù)查詢出響應(yīng)數(shù)據(jù),不僅節(jié)省了服務(wù)器的帶寬也降低了后端服務(wù)的壓力;

怎么理解緩存

怎么理解緩存

對比之后得出結(jié)論:通常來說為了降低后端服務(wù)的壓力ETag適用于圖片/js/css等靜態(tài)資源,而類似用戶詳情信息需要調(diào)用后端服務(wù)的數(shù)據(jù)適合使用Last-Modified來處理

Nginx

通常情況下我們都會使用到Nginx來做反向代理服務(wù)器,我們可以通過緩沖、緩存來對Nginx進行調(diào)優(yōu),本篇我們就從這兩個方面來聊聊Nginx調(diào)優(yōu)

緩沖

默認(rèn)情況下,Nginx在返回響應(yīng)給客戶端之前會盡可能快的從上游服務(wù)器獲取數(shù)據(jù),Nginx會盡可能的將上有服務(wù)器返回的數(shù)據(jù)緩沖到本地,然后一次性的全部返回給客戶端,如果每次從上游服務(wù)器返回的數(shù)據(jù)都需要寫入到磁盤中,那么Nginx的性能肯定會降低;所以我們需要根據(jù)實際情況對Nginx的緩存做優(yōu)化。

  • proxy_buffer_size: 設(shè)置Nginx緩沖區(qū)的大小,用來存儲upstream端響應(yīng)的header。

  • proxy_buffering: 啟用代理內(nèi)容緩沖,當(dāng)該功能禁用時,代理一接收到上游服務(wù)器的返回就立即同步的發(fā)送給客戶端,proxy_max_temp_file_size被設(shè)置為0;通過設(shè)置proxy_buffering為on,proxy_max_temp_file_size為0 可以確保代理的過程中不適用磁盤,只是用緩沖區(qū); 開啟后proxy_buffersproxy_busy_buffers_size參數(shù)才會起作用

  • proxy_buffers: 設(shè)置響應(yīng)上游服務(wù)器的緩存數(shù)量和大小,當(dāng)一個緩沖區(qū)占滿后會申請開啟下一個緩沖區(qū),直到緩沖區(qū)數(shù)量到達設(shè)置的最大值

  • proxy_busy_buffers_size: proxy_busy_buffers_size不是獨立的空間,他是proxy_buffersproxy_buffer_size的一部分。nginx會在沒有完全讀完后端響應(yīng)就開始向客戶端傳送數(shù)據(jù),所以它會劃出一部分busy狀態(tài)的buffer來專門向客戶端傳送數(shù)據(jù)(建議為proxy_buffers中單個緩沖區(qū)的2倍),然后它繼續(xù)從后端取數(shù)據(jù)。 proxy_busy_buffer_size參數(shù)用來設(shè)置處于busy狀態(tài)的buffer有多大。

1)如果完整數(shù)據(jù)大小小于busy_buffer大小,當(dāng)數(shù)據(jù)傳輸完成后,馬上傳給客戶端;

2)如果完整數(shù)據(jù)大小不小于busy_buffer大小,則裝滿busy_buffer后,馬上傳給客戶端;

典型是設(shè)置成proxy_buffers的兩倍。

怎么理解緩存

Nginx代理緩沖的設(shè)置都是作用到每一個請求的,想要設(shè)置緩沖區(qū)的大小到最佳狀態(tài),需要測量出經(jīng)過反向代理服務(wù)器器的平均請求數(shù)和響應(yīng)的大?。?code>proxy_buffers指令的默認(rèn)值 8個 4KB 或者 8個 8KB(具體依賴于操作系統(tǒng)),假如我們的服務(wù)器是1G,這臺服務(wù)器只運行了Nginx服務(wù),那么排除到操作系統(tǒng)的內(nèi)存使用,保守估計Nginx能夠使用的內(nèi)存是768M

  1. 每個活動的連接使用緩沖內(nèi)存:8個4KB = 8 * 4 * 1024 = 32768字節(jié)

  2. 系統(tǒng)可使用的內(nèi)存大小768M: 768 * 1024 * 1024 = 805306368字節(jié)

  3. 所以Nginx能夠同時處理的連接數(shù):805306368 / 32768 = 24576

經(jīng)過我們的粗略估計,1G的服務(wù)器只運行Nginx大概可以同時處理24576個連接。

假如我們測量和發(fā)現(xiàn)經(jīng)過反向代理服務(wù)器響應(yīng)的平均數(shù)據(jù)大小是 900KB , 而默認(rèn)的 8個4KB的緩沖區(qū)是無法滿足的,所以我們可以調(diào)整大小

http {
    proxy_buffers 30 32k;
}

這樣設(shè)置之后每次請求可以達到最快的響應(yīng),但是同時處理的連接數(shù)減少了,(768 * 1024 * 1024) / (30 * 32 * 1024)=819個活動連接;

如果我們系統(tǒng)的并發(fā)數(shù)不是太高,我們可以將proxy_buffers緩沖區(qū)的個數(shù)下調(diào),設(shè)置稍大的proxy_busy_buffers_size加大往客戶端發(fā)送的緩沖區(qū),以確保Nginx在傳輸?shù)倪^程中能夠把從上游服務(wù)器讀取到的數(shù)據(jù)全部寫入到緩沖區(qū)中。

http {
    proxy_buffers 10 32k;
    proxy_busy_buffers_size 64k;
}

緩存

怎么理解緩存

Nignx除了可以緩沖上游服務(wù)器的響應(yīng)達到快速返回給客戶端,它還可以是實現(xiàn)響應(yīng)的緩存,通過上圖我們可以看到

  • 1A: 一個請求到達Nginx,先從緩存中嘗試獲取

  • 1B: 緩存不存在直接去上游服務(wù)器獲取數(shù)據(jù)

  • 1C: 上游服務(wù)器返回響應(yīng),Nginx把響應(yīng)放入到緩存

  • 1D: 把響應(yīng)返回到客戶端

  • 2A: 另一個請求達到Nginx, 到緩存中查找

  • 2B: 緩存中有對應(yīng)的數(shù)據(jù),直接返回,不去上游服務(wù)器獲取數(shù)據(jù)

Nginx的緩存常用配置:

  • proxy_cache_path: 放置緩存響應(yīng)和共享的目錄。levels 設(shè)置緩存文件目錄層次, levels=1:2 表示兩級目錄,最多三層,其中 1 表示一級目錄使用一位16進制作為目錄名,2 表示二級目錄使用兩位16進制作為目錄名,如果文件都存放在一個目錄中,文件量大了會導(dǎo)致文件訪問變慢。keys_zone設(shè)置緩存名字和共享內(nèi)存大小,inactive 當(dāng)被放入到緩存后如果不被訪問的最大存活時間,max_size設(shè)置緩存的最大空間

  • proxy_cache: 定義響應(yīng)應(yīng)該存放到哪個緩存區(qū)中(keys_zone設(shè)置的名字)

  • proxy_cache_key: 設(shè)置緩存使用的Key, 默認(rèn)是完整的訪問URL,可以自己根據(jù)實際情況設(shè)置

  • proxy_cache_lock: 當(dāng)多個客戶端同時訪問一下URL時,如果開啟了這個配置,那么只會有一個客戶端會去上游服務(wù)器獲取響應(yīng),獲取完成后放入到緩存中,其他的客戶端會等待從緩存中獲取。

  • proxy_cache_lock_timeout: 啟用了proxy_cache_lock之后,如果第一個請求超過了proxy_cache_lock_timeout設(shè)置的時間默認(rèn)是5s,那么所有等待的請求會同時到上游服務(wù)器去獲取數(shù)據(jù),可能會導(dǎo)致后端壓力增大。

  • proxy_cache_min_uses: 設(shè)置資源被請求多少次后才會被緩存

  • proxy_cache_use_stale: 在訪問上游服務(wù)器發(fā)生錯誤時,返回已經(jīng)過期的數(shù)據(jù)給客戶端;當(dāng)緩存內(nèi)容對于過期時間不敏感,可以選擇采用這種方式

  • proxy_cache_valid: 為不同響應(yīng)狀態(tài)碼設(shè)置緩存時間。如果設(shè)置proxy_cache_valid 5s,那么所有的狀態(tài)碼都會被緩存。

設(shè)置所有的響應(yīng)被緩存后最大不被訪問的存活時間6小時,緩存的大小設(shè)置為1g,緩存的有效期是1天,配置如下:

http {
    proxy_cache_path /export/cache/proxy_cache keys_zone=CACHE:10m levels=1:2 inactive=6h max_size=1g;
    server {
        location / {
            proxy_cache CACHE; //指定存放響應(yīng)到CACHE這個緩存中
            proxy_cache_valid 1d; //所有的響應(yīng)狀態(tài)碼都被緩存1d
            proxy_pass: http://upstream;
        }
    }
}

如果當(dāng)前響應(yīng)中設(shè)置了Set-Cookie頭信息,那么當(dāng)前的響應(yīng)不會被緩存,可以通過使用proxy_ignore_headers來忽略頭信息以達到緩存

proxy_ignore_headers Set-Cookie

如果這樣做了,我們需要把cookie中的值作為proxy_cache_key的一部分,防止同一個URL響應(yīng)的數(shù)據(jù)不同導(dǎo)致緩存數(shù)據(jù)被覆蓋,返回到客戶端錯誤的數(shù)據(jù)

proxy_cache_key "$host$request_uri$cookie_user"

注意,這種情況還是有問題,因為在緩存的key中添加cookie信息,那么可能導(dǎo)致公共資源被緩存多份導(dǎo)致浪費空間;要解決這個問題我們可以把不同的資源分開配置,比如:

server {
    proxy_ignore_headers Set-Cookie;
    
    location /img {
        proxy_cache_key "$host$request_uri";
        proxy_pass http://upstream;
    }
    
    
    location / {
        proxy_cache_key "$host$request_uri$cookie_user";
        proxy_pass http://upstream;
    }
}

清理緩存

雖然我們設(shè)置了緩存加快了響應(yīng),但是有時候會遇到緩存錯誤的請求,通常我們需要為自己開一個后面,方便發(fā)現(xiàn)問題之后通過手動的方式及時的清理掉緩存。Nginx可以考慮使用ngx_cache_purge模塊進行緩存清理。

location ~ /purge/.* {
    allow 127.0.0.1;
    deny all;
    proxy_cache_purge cache_one $host$1$is_args$args
}

該方法要限制訪問權(quán)限proxy_cache_purge緩存清理的模塊,cache_one指定的key_zone,$host$1$is_args$args 指定的生成緩存key的參數(shù)

存儲

如果有大的靜態(tài)文件,這些靜態(tài)文件基本不會別修改,那么我們就可以不用給它設(shè)置緩存的有效期,讓Nginx直接存儲這些文件直接。如果上游服務(wù)器修改了這些文件,那么可以單獨提供一個程序把對應(yīng)的靜態(tài)文件刪除。

http {
    proxy_temp_path /var/www/tmp;
    
    server {
        root /var/www/data;
        
        location /img {
            error_page 404 = @store
        }
        
        location @store {
            internal;
            proxy_store on;
            proxy_store_access group:r all:r;
            proxy_pass http://upstream;
        }
    }
}

請求首先會去/img中查找文件,如果不存在再去上游服務(wù)器查找;internal 指令用于指定只允許來自本地 Nginx 的內(nèi)部調(diào)用,來自外部的訪問會直接返回 404 not found 狀態(tài)。proxy_store表示需要把從上游服務(wù)器返回的文件存儲到 /var/www/data; proxy_store_access設(shè)置訪問權(quán)限

“怎么理解緩存”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!


文章題目:怎么理解緩存
網(wǎng)站網(wǎng)址:http://weahome.cn/article/gsiogj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部