從總體上來看,對於大型網站,比如門戶網站,在面對大量用戶訪問、高並發請求方面,基本的解決方案集中在這樣幾個環節:
1.首先需要解決網絡帶寬和Web請求的高並發,需要合理的加大服務器和帶寬的投入,並且需要充分的利用系統中軟件、硬件的緩存機制,將能緩存的內容都進行緩存存儲,減少計算層和存儲層的壓力。
2.其次需要對業務服務器和業務支撐服務器進行合理的分層,並且采用並行計算和分布式算法對大量計算進行處理,並且在開發的過程中需要采用Java SDK中並發包(Concurrency)進行編碼實現。
3.存儲層需要采用分布式文件服務器和列式的存儲服務器進行構建,支撐海量數據的存放和讀取,並且還要對關系型數據進行深層次的配置參數優化。
4.我們還需要清楚的認識到,將來根據系統運行的狀態以及平台中不同的業務場景循序漸進的進行調整和優化。
對於大型系統來說,采用的技術是涉及面非常廣,從硬件到軟件、編程語言、數據庫、WebServer、防火牆等各個領域都有了很高的要求。在面對大量用戶訪問、高並發請求方面,基本的解決方案集中在這樣幾個環節:將會使用高性能的服務器、高性能的數據庫、高效率的編程語言、還有高性能的Web容器。但是除了這幾個方面,還沒法根本解決面臨的高負載和高並發問題,所以需要將計算和負載的壓力分載到每個計算機上,使用不同的服務器集群機組進行分布式和並行計算,面對所產生的壓力。
具體每個環節的一些常用手段:
一、應用服務器負載均衡
1、鏈路負載均衡
通過DNS解析域名時,將客戶端的訪問解析成不同的IP,分配到不同的入口,同時盡可能保證所訪問的入口是所有入口中可能較快的一個。
2、軟件負載均衡
訪問時生成頁面的任務會被分配給其中一台服務器完成,這個過程要保證公正、公平、平均。軟件四層交換我們可以使用Linux上常用的LVS來解決,LVS就是Linux Virtual Server。
3、硬件負載均衡
第四層交換使用第三層和第四層信息包的報頭信息,根據應用區間識別業務流,將整個區間段的業務流分配到合適的應用服務器進行處理。在第四層交換中的應用區間則由源端和終端IP地址、TCP和UDP端口共同決定。在硬件四層交換產品領域,有一些知名的產品可以選擇,比如Alteon、F5等。
最新:CDN加速技術。CDN的全稱是內容分發網絡。其目的是通過在現有的Internet中增加一層新的網絡架構,將網站的內容發布到最接近用戶的網絡“邊緣”,使用戶可以就近取得所需的內容,提高用戶訪問網站的響應速度。
二、圖片服務器分離
對於Web服務器來說,不管是Apache、IIS還是其他容器,圖片是最消耗資源的,於是我們有必要將圖片與頁面進行分離,這是基本上大型網站都會采用的策略,他們都有獨立的、甚至很多台的圖片服務器。這樣的架構可以降低提供頁面訪問請求的服務器系統壓力,並且可以保證系統不會因為圖片問題而崩潰。在應用服務器和圖片服務器上,可以進行不同的配置優化,比如apache在配置ContentType的時候可以盡量少支持、盡可能少的LoadModule,保證更高的系統消耗和執行效率。
三、頁面優化
1、減少請求次數
通過合並CSS和Javascript文件來減少請求次數或是將資源文件分布在多個域名下來繞過瀏覽器並發加載的限制。
2、壓縮CSS和Javascript代碼。
通過對文件代碼內容刪除換行和空格來減少代碼存儲空間。
3、優化圖片
通過對圖片進行截取和縮放大小來優化圖片,加快圖片加載速度。
4、HTML靜態化
利用FreeMarker將數據庫數據靜態化成html文件來提高訪問速度。適用場合:對於含有不要求實時性的內容的網頁可使用,如網站首頁,各模塊首頁的新聞,公告等等。
四、Java設計優化
1、設計模式
單例模式、代理模式、享元模式、裝飾者模式、觀察者模式。
2、緩存
如:使用Ehcache可以結合AOP,做業務層的方法緩存,以類名、方法名、參數名作為key,結果對象作為value。適用場合:對數據不經常更新,查詢方式比較固定。
3、緩沖
如:JDK的IO包中BufferedWriter
4、多線程
適用場合:群發郵件,大批量處理圖片,寫日志。典型的消費者生產者模式
5、對象池
如:數據庫連接池C3P0、線程池Executors、Apache的對象池Jakarta Commons Pool
6、分布式緩存
分布式緩存框架Terracotta,可實現分布式session、EhCachc等共享。
五、Java程序編碼優化
1、String
String的replace、substring方法會有內存泄露問題,用StringTokenizer取代split方法,charAt方法代替startsWith、endsWith方法,StringBuilder取代String並初始化預估的capacity。
2、List
查詢優先使用ArrayList,插入刪除優先使用LinkedList。如果插入數據在數組最后一位,則ArrayList性能好於LinkedList。
遍歷實現了RandomAccess接口的集合性能由高到低依次排序:索引下標>迭代器>增強for
3、Map
map對象里key值的hashCode方法決定集合的性能。
4、優化集合訪問代碼
創建集合對象時,初始化預估的capacity可提高性能。盡量使用內部元素來取代方法調用。
5、NIO
使用MappedByteBuffer來取代傳統IO來進行文件讀寫。
6、引用
在適當時候緩存可以用弱引用或是軟引用來實現,如:WeakHashMap。
7、異常
盡量避免在循環體內使用異常捕獲。
8、位運算代替乘除運算
六、數據庫優化
1、分表
通過對記錄ID取模或時間維度的規則進行分表。
2、分區
Oracle數據庫支持分區,可以根據某個列的數據規則進行分區。
3、中間表
將原數據根據想得到的目標數據進行一系列的處理做出一套中間表,直接從中間表中進行查詢,通過定時調度定時更新中間表。適用場合:對數據內容實時性要求不高,如:數據分析。
4、歷史歸檔
可根據時間整理出很少用到的數據集抽到歷史表中,數據表只留常用數據,可以利用對象序列化反序列化來實現。適用場合:對歷史數據極少訪問。
5、列式存儲
MySQL開源數據倉庫Infobright,對高壓縮比數據存儲,查詢速度可提高5~60倍,免費版不支持DML語句,不支持高並發,只能支持10多個並發查詢,可通過load導入csv數據文件。適用場合:對數據不經常更新並且實時性要求不高,如:數據分析。
6、查詢緩存
MySQL Query Cache,Oracle Result Cache,可通過修改數據庫配置文件來實現查詢緩存,sql語句作為key,結果作為value的緩存方式,當數據表發生改變時相應的cache就會失效。適用場合:對數據不經常更新,查詢方式比較固定。注:支持表連接,但不支持函數
7、建索引
對於使用較復雜的sql,對大數據量表查詢時候,可采用建索引的方式,將涉及到的查詢條件字段,可提高查詢速度。
8、sql優化
sql語句中,select后盡量明確字段名來代替*來減少查詢列。盡量少使用in關鍵字,可通過left join和exists關鍵字取代。
9、存儲過程
存儲過程只需編譯一次,適用場合:當對數據庫進行復雜操作時。如:多表的查詢,計算,更新。
10、數據庫服務器集群,讀寫分離。
七、JVM調優。
1、確定堆內存大小(-Xmx、-Xms)。
2、合理分配新生代和老年代(-XX:NewRatio、-Xmn、-XX:SurvivorRatio)。
3、確定永久區大小(-XX:Permsize、-XX:MaxPermSize)。
4、選擇垃圾收集器(CMS、G1等)、對垃圾收集器合理設置。
5、禁用顯示GC(-XX:+DisableExplicitGC)。
6、禁用類元數據回收(-Xnoclassgc)。
7、禁用類驗證(-Xverify:none)。
8、JVM增加內存參數-Xms256M -Xmx1024M -XX:MaxNewSize=512m -XX:MaxPermSize=512m
七、需求上解決:如果性能瓶頸的模塊的需求是可有可無,可以考慮屏蔽掉此需求。
八、性能調優工具
1.JMeter、LoadRunner:性能測試、壓力測試。
2.JConsole、JProfiler:監控堆信息、線程、永久區使用情況、類加載情況等。
3.Visual VM:故障診斷、性能監控。