亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

緩存(二)

系統(tǒng) 1803 0

? 在我們打開瀏覽器 , 決定瀏覽某個(gè)網(wǎng)頁之前 ( 指人眼看到屏幕上的內(nèi)容之前 ), 一般來說瀏覽器有幾個(gè)事情要做 , 首先根據(jù) url 請(qǐng)求服務(wù)器端的 html html 顯示到屏幕上等等 . à 下載 css, js,-------- à , 然后解析 html,------ à 數(shù)據(jù) ------ 接著大腦才能感受到 . à 然后眼睛才能感受到 ,-------- à ---------

在這個(gè)流程中 , 那么怎么才能讓大腦盡可能快的接受到這個(gè)信息呢 , 我想最快的方式是在大腦里放一份該屏幕的拷貝 , 下次想看這份內(nèi)容的時(shí)候直接拿出大 腦的拷貝就可以了 . 如果大腦容量有限 , 那我們可以考慮把這份拷貝放到眼睛里 , 如果眼睛也放不下 , 那我們可以考慮把這份拷貝放到瀏覽器里 , 從這個(gè)邏輯上看 , 越靠近大腦的數(shù)據(jù)越能快速的被我們接受到 .

那么本文的目的其實(shí)就是為了研究如何使用大腦和眼睛來緩存數(shù)據(jù) ------------------------ 吃驚吧 ,ahuaxuan 瞎扯的 , 回到正題 , 上面這段調(diào)侃不是為了說明別的 , 而是為了說明越靠近用戶的數(shù)據(jù)被用戶感受到的速度就越快 . 也就是近與快的關(guān)系
.

接著再讓我們拋開緩存先不說 , 來說說 CDN 和鏡像的問題 ,CDN 的英文名字叫 CDN, 中文名字一般還是 CDN( 請(qǐng)換個(gè)調(diào)朗誦 ). 呵呵 ,CDN 中文名字是內(nèi) 容分布網(wǎng)絡(luò) , 簡單來說就是把內(nèi)容分布出去 , 比如放到全國幾個(gè)地方 , 舉例來說做一個(gè)圖片服務(wù) , 上海的用戶請(qǐng)求某個(gè)圖片服務(wù)器 , 那么只需要返回某個(gè)離上海最近 CDN 節(jié)點(diǎn)上的圖片 , 而不需要路由到北京或者云南的節(jié)點(diǎn)上去取數(shù)據(jù) , 您要問為啥呢 , 因?yàn)榭彀? , 上海的用戶訪問北京節(jié)點(diǎn)的數(shù)據(jù)顯然在路由層次上 , 網(wǎng)絡(luò)時(shí)間 消耗上都要多出很多 , 這說明啥呀 , 還是那個(gè)理兒 : 近就會(huì)快啊


一般來說 CDN 都是放一些圖片 , 視頻 , 文檔之類的數(shù)據(jù) , 那么元數(shù)據(jù)呢 , 放一塊兒 , 當(dāng)然也不是 , 這時(shí)候可以用鏡像來解決元數(shù)據(jù)的問題 , 于是變成了上海的用戶訪問上海的鏡像 , 北京的用戶訪問北京的鏡像 . 這還不是就地取材比較方便嘛
.

, 說到這里 , 想必大家對(duì)近和快的關(guān)系有了一定的認(rèn)識(shí)了 , 下面我們來看看如何把這種原理或者規(guī)則運(yùn)用到緩存中去
.

下面讓 ahuaxuan 和大家先調(diào)查一下離眼睛最近的是什么 , 顯示器 ( 別跟我說是屏幕保護(hù)膜和鍵盤哈 , 鼠標(biāo)也不行 ), 不過這些是硬件呀 , 那軟的 , 非瀏覽器莫數(shù)了 . 也就是說如果我們把一些可以緩存在瀏覽器上的數(shù)據(jù)緩存到瀏覽器上 , 那就能加快我們的頁面響應(yīng)速度了 . 也就是說我們現(xiàn)在找到一個(gè)地方 , 也許可以放一點(diǎn)可以緩存的數(shù)據(jù)
.

下面我們要考察考察什么樣的數(shù)據(jù)可以緩存在瀏覽器上 , 以及緩存在瀏覽器上的一些優(yōu)缺點(diǎn)或者限制因素

什么樣的數(shù)據(jù)可以緩存在瀏覽器上
?
瀏覽器上無法就幾種數(shù)據(jù) ,html,css,js,image, . 那么接著我們來看看他們的變化特性
,
html
數(shù)據(jù)很多情況下是動(dòng)態(tài)的 , 但是也有很多情況下是某個(gè)時(shí)間段內(nèi)可以是靜態(tài)的
.
Css
一般是靜態(tài)的

Js
一般也是靜態(tài)的

Image
一般也是靜態(tài)的
.

, 看上去后幾者基本都可以緩存在瀏覽器 , html 是否緩存要看 html 中數(shù)據(jù)的特性了 . 那么問題來了 , 瀏覽器是依據(jù)什么設(shè)置來緩存 html, 或者 css, 或者 js 的呢 . 答曰 ,expires 或者 max-age.
Expires
代表該份數(shù)據(jù)緩存到瀏覽器上 , 直到某個(gè)時(shí)間點(diǎn)后過期 , max-age 表示緩存在瀏覽器上直到某個(gè)時(shí)間段之后過期
.

對(duì)于靜態(tài)內(nèi)容:設(shè)置文件頭過期時(shí)間 Expires 的值為 “Never expire” (永不過期)

動(dòng)態(tài)頁面 , 在代碼中添加 cache-control, 表示多少時(shí)間之后過期 ,
:
response.setHeader("Cache-Control", "max-age=3600");
表示 1 個(gè)小時(shí)后過期 , 即在瀏覽器上緩存一個(gè)小時(shí)
.

但是這樣問題又來了 , 如果設(shè)置 10 天后過期 , 那我明天就要改變 ,css,js 都變了 , 咋辦吶 , 答曰 , 加版本號(hào)吧 , 這樣瀏覽器就會(huì)重新加載新的 css js
.
但是如果是動(dòng)態(tài)數(shù)據(jù) , 那就沒有折了 , 所以動(dòng)態(tài)數(shù)據(jù)的 max-age 一般不推薦太大 , 否則啊 , 您吶 , 就得挨個(gè)通知您得用戶按一下 Ctril+F5
.

一般來說靜態(tài)數(shù)據(jù)需要緩存 , 我們一般通過 webserver( apache,lighttpd 之流 ), 只需要配置一下即可 , 而動(dòng)態(tài)數(shù)據(jù)是比較重 要的 , 因?yàn)槠涓淖兊闹芷诙? , 而且只能由 servlet 容器或者 fastcgi 之類的服務(wù)器返回 , 所以其應(yīng)付大量并發(fā)的能力是有限的 . 那么這里理論上可能有 一個(gè)瓶頸 , 就是如果訪問的獨(dú)立用戶較多 , 那么這份動(dòng)態(tài)數(shù)據(jù)還是會(huì)被請(qǐng)求 1* 用戶數(shù) = n , 那么我們可以想象 , 一樣的請(qǐng)求對(duì)于我們的 servlet 容器或者 fastcgi 來說其實(shí)是多余的 , 我們可以想一個(gè)方法 , 把這些一樣的請(qǐng)求擋在 servlet 容器或者 fastcgi 進(jìn)程之前
.

正如在第一說中說到的 , 在瀏覽器和 servlet 容器或者 fastcgi 進(jìn)程之間 , 還有很大的空間可以發(fā)揮 , 在這一部分的緩存 ,ahuaxuan 稱之為
webcache.

目前在 webcache , 最流行的估計(jì)就屬 squid , 然后還有 varnish 等等 . 為了有一個(gè)比較直觀的感受 , 我們來看看下面這張圖唄
:

緩存(二)
?
從這張圖上 , 我們可以看出 , 瀏覽器 1 在請(qǐng)求了一份數(shù)據(jù)之后 , 其實(shí)這份數(shù)據(jù)已經(jīng)在 webcache 上了 , 瀏覽器再來請(qǐng)求 2 的時(shí)候 , 請(qǐng)求到了 webcache 這層就返回了 , 這樣就降低了 servlet container 的壓力了 . 雖然說我們?cè)? servlet 容器上也是可以建 page cache, 但是畢竟 servlet 本身的并發(fā)能力有限 .( 如何在 servlet container 上使用 page cache : http://www.iteye.com/topic/128458 )

而且更重要的是一般 webcache 的并發(fā)能力要比 servlet container 或者 fastcgi process 要高出很多 ( 沒辦法 , 誰叫它是專業(yè)的 cache ). 所以使用 webcache 也能夠提供更高訪問量的服務(wù) . 一舉多得 , 何樂而不為呢 . 但是聲明一下 , 您吶 , 別以為上 面這種方式是標(biāo)準(zhǔn)方式 , 我們還有 webserver, 負(fù)載均衡器等等 , 上圖只是為了便于說明本文的論點(diǎn) , 而且互連網(wǎng)需求和解決方案層出不窮 , 切不可以胡搬 亂套 , 還是要分析分析再分析 , 思考 , 思科再思考 .

說到這里即使以前沒有接觸過得筒子大概也明白了 web cache 得作用了 . 下面我們?cè)賮砜纯慈绾问褂? web cache , 呵呵 , 其實(shí)和瀏覽器上緩存數(shù)據(jù)得方式一樣 . 也是通過在 response header 中指定 expires 或者 max-age 來實(shí)現(xiàn)的 .( 但是據(jù) ahuaxuan 觀察在使用 squid 的時(shí)候有一個(gè)要求 , 瀏覽器的請(qǐng)求必須滿足 http 的語義 , 也就是說只有 method=get 的時(shí)候 web cache 才能緩存數(shù)據(jù) , 如果是 post, 那么 web cache 認(rèn)為這個(gè)是一個(gè)創(chuàng)建數(shù)據(jù)的請(qǐng)求 , 并不會(huì)緩存其返回結(jié)果
.)

Squid,
如果您要系統(tǒng)的學(xué)習(xí) squid, 請(qǐng)看
:
http://www.squid-cache.org/ ????? http://blog.s135.com/book/squid/

補(bǔ)充 , 在有些情況下 ,web cache 中的數(shù)據(jù)很有可能是有狀態(tài)的 . 比如根據(jù)瀏覽器的 locale 返回不同的數(shù)據(jù) , 那么雖然訪問的 url 是一樣的 , 但是返回的值卻是不一樣的 , 咋辦 , 別擔(dān)心 , 我們有 vary, 只要在 response 里指定 vary 參數(shù)為 accept-language ok. 您也可以指定為 cookie 中的值 , 就完全看您的需要了 . 如果您還是不明白 vary 的作用 , 請(qǐng)看 : http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44

總結(jié) :
說到這里 , 關(guān)于近和快的話題也基本可以結(jié)束了 ( 這個(gè)話題再寫下去就變成裹腳布了 ). 所以一般情況下 , 我們可以認(rèn)為有如下事實(shí) :” == ”, 但是 近和快并不只是表現(xiàn)在人的體驗(yàn)上 , 如果換個(gè)角度 , 速度的感受者不是人 , 而是機(jī)器 , 那么我們也可以這么認(rèn)為 local cache remote cache 更靠近 cpu, 所以 local cache 的速度更快 ( 當(dāng)然他們的功能不是重疊的 , 各自適用的場(chǎng)景不一樣而已 , 而且很多情況下他們可以配合使用 , 在后續(xù)的文章中將會(huì)討論這個(gè)問題

).

如何在只使用 tomcat 的情況下 , 自動(dòng)緩存 js css 或者 image 等文件 .
第一步 : 寫一個(gè) filter, 可以根據(jù)路徑的正則來判斷該路徑的請(qǐng)求是否需要設(shè)置 max-age:

    public class CacheFilter implements Filter{  
  
    private static transient Log logger = LogFactory.getLog(CacheFilter.class);  
      
    private Integer cacheTime = 3600 * 24;  
    private List<Pattern> patternList = new ArrayList<Pattern>();  
      
    private static ResourceBundle rb = ResourceBundle.getBundle("cache-pattern");  
    public void destroy() {  
          
    }  
  
    public void doFilter(ServletRequest rq, ServletResponse rqs,  
            FilterChain fc) throws IOException, ServletException {  
          
        fc.doFilter(rq, rqs);  
        if (rq instanceof HttpServletRequest && rqs instanceof HttpServletResponse) {  
            HttpServletRequest request = (HttpServletRequest) rq;  
            HttpServletResponse response = (HttpServletResponse) rqs;  
              
            if (matchPattern(request.getRequestURI())) {  
                response.setHeader("Cache-Control", "max-age=" + cacheTime);  
                if (logger.isDebugEnabled()) {  
                    StringBuilder sb = new StringBuilder();  
                    sb.append(" set cache control for uri = ").append(request.getRequestURI());  
                    sb.append(" and the cache time is ").append(cacheTime).append(" second");  
                    logger.debug(sb.toString());  
                }  
            }  
          
        } else {  
            if (logger.isWarnEnabled()) {  
                logger.warn("---- the request instance is not instanceof HttpServletRequest ---");  
                logger.warn("---- the response instance is not instanceof HttpServletResponse ---");  
            }  
        }  
          
    }  
  
    public void init(FilterConfig arg0) throws ServletException {  
        Enumeration<String> keys = rb.getKeys();  
        while (keys.hasMoreElements()) {  
            String p = keys.nextElement();  
            String value = rb.getString(p);  
            patternList.add(Pattern.compile(value, Pattern.CASE_INSENSITIVE));  
              
            if (logger.isInfoEnabled()) {  
                logger.info(">>>>>>>>>>> init the cache pattern " + value);  
            }  
        }  
          
        if (arg0 != null) {  
            String ct = arg0.getInitParameter("cache-time");  
            if (!"".equals(ct) && null != ct) {  
                cacheTime = new Integer(ct);  
                if (logger.isInfoEnabled()) {  
                    logger.info(">>>>>>>>>> the cache time is " + cacheTime);  
                }  
            }  
        }  
    }  
      
    private boolean matchPattern(String url) {  
        for (Pattern pattern : patternList) {  
            if (pattern.matcher(url).matches()) {  
                return true;  
            }  
        }  
          
        return false;  
    }  
  
    public static void main(String [] args) throws ServletException {  
        CacheFilter cf = new CacheFilter();  
        cf.init(null);  
        System.out.println(cf.matchPattern("/css/prototype.CSS"));  
    }  
}  

  

?

第二步 : classpath 路徑下創(chuàng)建一個(gè) cache-pattern.properties 文件 , 內(nèi)容如下 :

Java 代碼

1?=?.*ext-all.js??

2?=?.*prototype.js??

3?=?.*/css/.*\\.css??

1 = .*ext-all.js

2 = .*prototype.js

3 = .*/css/.*\\.css


在這個(gè)配置文件中 , 您可以根據(jù) js css 的路徑來配置哪些目錄 , 或者哪些文件需要設(shè)置 max-age.

第三步 :
web.xml 添加如下內(nèi)容 :

Java 代碼

<filter>??

?????????<filter-name>cache-filter</filter-name>??

?????????<filter-class>com.filter.CacheFilter</filter-class>??

?????????<init-param>??

????????????<param-name>cache-time</param-name>??

????????????<param-value>86000</param-value>??

????????</init-param>??

????</filter>??

??

<filter-mapping>??

????????<filter-name>cache-filter</filter-name>??

????????<url-pattern>*.js</url-pattern>??

????</filter-mapping>??

??????

????<filter-mapping>??

????????<filter-name>cache-filter</filter-name>??

????????<url-pattern>*.css</url-pattern>??

</filter-mapping>??

<filter>

??????? ? <filter-name>cache-filter</filter-name>

??????? ? <filter-class>com.filter.CacheFilter</filter-class>

??????? ? <init-param>

??????????? <param-name>cache-time</param-name>

??????????? <param-value>86000</param-value>

??????? </init-param>

??? </filter>

?

<filter-mapping>

??????? <filter-name>cache-filter</filter-name>

??????? <url-pattern>*.js</url-pattern>

??? </filter-mapping>

???

??? <filter-mapping>

??????? <filter-name>cache-filter</filter-name>

??????? <url-pattern>*.css</url-pattern>

</filter-mapping>



如此 3 , 就可以將 js css 文件緩存于無形 . 快哉 .

倉卒之間成文 , 再加上 ahuaxuan 水平有限 , 本文如有紕漏之處 , 還望各位看官您不吝指正 , 先謝過了 .

?

?

?

?

?

?

?

?

?

緩存(二)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 清纯唯美亚洲综合日韩第 | 国产综合精品在线 | 狠狠久久亚洲欧美专区 | 国内精品视频在线 | 中国产一级毛片 | 国产一区二区三区免费在线视频 | 国产精品福利视频手机免费观看 | 天天草夜夜操 | 日日夜夜操操操 | 91香蕉国产亚洲一区二区三区 | 夜夜夜夜夜夜爽噜噜噜噜噜噜 | 99se亚洲综合色区 | 久久免费视频1 | 九九99热| 午夜国产精品福利在线观看 | 精品视频在线一区 | 日韩有码在线播放 | 成人国内精品久久久久影院 | 97视频免费上传播放 | 成人永久免费视频网站在线观看 | 天天视频国产免费入口 | 91论坛在线 | 深夜激情网站 | 日本一区精品 | 欧美日本视频一区 | 可以看美女隐私的网站 | 性生活免费视频网站 | 奇米影视狠狠 | 日韩人成免费网站大片 | 久久精品久噜噜噜久久 | 国产全黄a一级毛片视频 | 鲁啊鲁在线视频 | 米奇777第四久久久99 | 久久香蕉国产线看免费 | 99热久久精品免费精品 | 毛片一级 | 在线观看国产福利 | 午夜国产在线观看 | 国产一区二区中文字幕 | 亚洲精品二区 | 天天做日日做 |