1. 程式人生 > >電商網站,效能優化

電商網站,效能優化

問題:

1)當大型網站系統>10萬人

一個小時內,會跟資料庫互動10萬次(國內有京東,淘寶),這就會出現資料庫瓶頸,每個資料庫最大連線數(socket)2000
在某一段短暫時間內1萬人,會跟資料庫發生1萬次互動,2000-8000【30秒】 5000 3000
2000個使用者很快就可以到頁面
5000個使用者訪問頁面比較慢
還有3000個使用者會提示超時/伺服器出現例外

這是訪問效能的問題,原因是資料庫瓶頸。

解決方案:
1>頁面靜態化
解決方案:使用模板技術(Velocity[9-10年]/Freemarket[5-6年])

2>2>快取技術 (當資料更新比較快,幾秒鐘就更新一次,或者需要實時反映資料變化,或者頁面具有很多種風格,不便於生成靜態頁面。如BBS)

    A.頁面快取(view,html程式碼)

缺點:不能做到實時更新,優點:比二級快取效率更高。 
        在快取的有效期內,顯示的資料是沒有變化的,只有當快取過期以後才會有變化。
        頁面快取分為區域性快取和全域性快取,全域性快取是快取整個頁面的html程式碼,頁面快取是快取頁面中的某一塊區域的html程式碼。
        快取的範圍:application範圍(所有人都能共享,比如說產品列表顯示)session(只針對某一個訪問者,比如說快取某個使用者的個人資訊)
        OSCache預設的範圍是application範圍,可以通過scope屬性來修改。


        快取預設的有效時間是3600秒,也就是一小時。可以通過time屬性來修改。
        refresh屬性h如果設定為true,則可以強行清楚快取。
        key屬性的作用:如果不設定key屬性,就根據使用者輸入的url來做快取,如果使用者輸入的url改變,快取也會改變。oscatche會把所有的值放到一個map中,通過   key value來做判斷。

<body> <oscache:cache key="aaron" scope="session" time="15" refresh="${param.refresh }"> <div>
<%=new Date() %> </div> </oscache:cache> <br> 當前時間:<%=new Date() %> </body> 人為清除快取<flush/>標籤: <oscache:flush scope="application" />清除application範圍內的所有快取 <oscache:flush scope="session" key="foobar" />清除session範圍內的key為foobar的快取 <oscache:flush scope="application" group="currencyData" />清除application範圍內組名為currencyData的所有快取。 使用oscache實現頁面的全域性快取 <filter> <filter-name>CacheFilter</filter-name> <filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class> <init-param> <param-name>time</param-name> <param-value>7200</param-value> </init-param> <init-param> <param-name>scope</param-name> <param-value>application</param-value> </init-param> </filter> <filter-mapping> <filter-name>CacheFilter</filter-name> <url-pattern>/product/list/*</url-pattern> </filter-mapping>

  快取的key將以請求的uri+查詢字元竄組成,如果你訪問/oscache/index.jsp?name=tt和/oscache/index.jsp?name=ppp將得到兩分快取。
        快取在初次訪問頁面時進行,後續的請求將會返回快取中的內容。快取中存放的內容為頁面返回給使用者的html程式碼。
        OSCache配置屬性介紹
        cache.memory=true指定是否使用記憶體快取,配置預設為true,即使用記憶體快取。
        cache.capacity=1000指定快取的容量,預設的容量是無限的,我們可以為他設定快取數量。
        如果要使用硬碟快取,我們可以這樣設定:
        cache.memory=false
        cache.path=d:\\cache(指定快取儲存的路徑,注意:路徑應該採用雙\\符號)
        cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener
        cache.persistence.class用於設計持久化類
        我們既要考慮頁面的數量,也要考慮機器的記憶體,如果記憶體不多的話容易引起記憶體耗盡,系統的效能反而下降。
        但是最好還是用記憶體快取,因為速度比較快,一般伺服器的記憶體都大於10g,用於快取產品列表頁面夠了。因為產品列表頁面不會太多,假設我們有幾萬個的話,有一兩個g就夠了。
        CacheFilter的實現原理:

複製程式碼
 1 CacheFilter{
2 doFilter(request,response,chain){
3 String urlpath=req....;
4 if(oscache.contains(urlpath)){
5 String content=OsCache.getKey(urlpath);
6 response.write(content);
7 }else{
8 CacheHttpServletResponseWrapper wrapper=new CacheHttpServletResponseWrapper(response)
9 chain.doFilter(request,wrapper);
10 String content=wrapper.getContent();//獲取伺服器網客戶端輸出的html程式碼
11 OScache.put(urlpath,content);
12 response.write(content);
13 }
14 }
15
16 public CacheHttpServletResponseWrapper entends HttpServletResponseWrapper{
17 private String content;
18 public CacheHttpServletResponseWrapper(HttpServletResponse response){
19 ....
20 }
21 public void write(String content){
22 this.content=content;
23 }
24 public String getContent(){
25 return content;
26 }
27 }
28 }
複製程式碼


        頁面快取比二級快取快的原因:當請求來之後系統就會交給過濾器,過濾器得到路徑以後就會把快取返回給客戶端。
        二級快取要經過action service 和jsp
    B.二級快取(model/業務層,domain物件)優點:實時更新
    EHCache OSCache jbossCache(分散式快取)
    第一步:匯入ehcache的ehcache.jar檔案(hibernate中有)
    第二部:在persistence.xml檔案中新增下面配置項: 

1 <property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider"/>
2 <property name="hibernate.cache.use_second_level_cache" value="true"/>
3 <property name="hibernate.cache.use_query_cache" value="false"/>

 第三步:在實體類上面標註@Cache(region="cn.aaron.bean.Person",usage=CacheConcurrencyStrategy.READ_WRITE)
    第四步:在classpath下面放入ehcache.xml,內容模板如下: 

複製程式碼
 1 <?xml version="1.0" encoding="UTF-8"?>
2 <ehcache>
3
4 <diskStore path="D:\cache" />
5
6 <defaultCache maxElementsInMemory="10000" eternal="false" overflowToDisk="true" 7 timeToIdleSeconds="120" 8 timeToLiveSeconds="180" 9 diskPersistent="false"10 diskExpiryThreadIntervalSeconds="60"/>
11
12 <cache name="cn.aaron.bean.Person" maxElementsInMemory="100"13 eternal="false" overflowToDisk="true"14 timeToIdleSeconds="300"15 timeToLiveSeconds="600" diskPersistent="false" />
16 </ehcache>
複製程式碼

  注意<cache>節點中的name屬性要和@Cache(region="cn.aaron.bean.Person",usage=CacheConcurrencyStrategy.READ_WRITE)中的region相同
    ehcache.xml檔案中各項屬性說明如下:
        defaultCache節點為預設的快取策略
        maxElementsInMemory 記憶體中最大允許的物件數量
        eternal 設定快取中的物件是否永遠不過期
        overflowToDisk 把溢位的物件放到硬碟上(對於本例而言,第1001個物件將存放在硬碟上)
        timeToIdleSeconds 指定快取物件空閒多長時間會過期,過期的物件會被清除掉
        timeToLiveSeconds 指定快取物件總的存活時間
        diskPersistent 當jvm結束時是否持久化物件
        diskExpiryThreadIntervalSeconds 指定專門用於清除過期物件的監聽執行緒的輪詢時間
    
3>資料來源 連線池裡面放一些連線物件
每次都能跟資料庫建立連線socket(client)----socket(資料庫)

4>SSI 對效能提升不是那麼明顯(有一點點作用)
Server Side Include, 通常稱為“伺服器端包含”技術。
使用了SSI技術的檔案預設的字尾名為.shtml,SSI技術通過在html檔案中加入SSI指令讓web伺服器在輸出標準HTML程式碼之前先解釋SSI指令,
並把解釋完成後的輸出結果和HTML程式碼一起返回給客戶端。
在大部分專案中,我們主要使用了SSI的包含指令<!-#include virtual="global/foot.jsp"-->,
他的作用類似於JSP中的<jsp:include page="/global/foot.jsp"/>標籤。
使用SSI主要有如下兩點優勢:
1 SSI技術是通用技術,它不受限於執行環境,在java,.net,CGI,ASP,PHP下都可以使用SSI技術
2 解釋SSI指令的效率比解釋JSP的效率快很多,因為Servlet規範提供了太多的功能,這些功能都需要servlet引擎進行解釋,所以效率比較低。
在目前,大部分的入口網站都是用SSI技術,解釋SSI檔案最佳的伺服器是Apache HTTP Server。
大型入口網站基本都使用這個來解釋SSI檔案。
配置實用SSI
目前主流的web伺服器都提供SSI實現,我們只需要開啟SSI功能就可以使用。
tomcat也可以,但是並不會提高效能,因為使用的還是servlet引擎 .