1. 程式人生 > >高效能分散式架構實踐(一)

高效能分散式架構實踐(一)

先把普通企業級基本效能優化的小方法複習下

JVM 引數調優

1.      使用64JDK 1.6+ & Tomcat 6+

2.      jvm記憶體優化

編輯tomcat/bin/目錄下catalina.batlinuxcatalina.sh,配置類似,請自行百度),在檔案開頭加上以下程式碼(注意先搜尋一下,不要重複設定)

3.   set JAVA_OPTS=-Xms512m -Xmx4096m -XX:PermSize=128m-XX:MaxPermSize=256m

以上設定的含義為:堆記憶體最小512M,最大4G,非堆記憶體最小128M,最大256M,對於系統規模小、訪問量不大的專案可酌情將

-Xmx4096m設定為-Xmx2048m(2G)

深度優化對於訪問量較大,整合比較複雜的系統,需要利用JDK中的記憶體分析工具,分析記憶體的變化情況(一般是在生產環境中分析實際記憶體使用情況),並酌情修改記憶體引數,如將堆記憶體的最大值設定為-Xmx8000m,一般最大值不超過系統記憶體的2/3

常用的分析工具有JDK bin目錄中的jconsole.exe jvisualvm.exe

HTTP 連線數調優

編輯tomcat/conf/目錄下server.xml,在訪問埠對應的<Connector>中增加和連線數相關的屬性:
minSpareThreads:最小空閒連線執行緒數,預設值10
maxSpareThreads(Tomcat6之前的版本有一個maxSpareThreads引數,但是在7中已經移除了):最大空閒連線執行緒數,
maxThreads:最大連線執行緒數,併發處理的最大請求數,預設值200
acceptCount:等待佇列,指定當所有可以使用的處理請求的執行緒數都被使用時,可以放到處理佇列中的請求數,超過這個數的請求將不予處理。預設值為100
connectionTimeout:請求超時時間,預設是20秒
推薦配置tomcat7:
<Connector port="8080" protocol="HTTP/1.1" maxThreads="800" minSpareThreads="50" acceptCount="800"
connectionTimeout="30000" redirectPort="8443" />
注:併發能力問題涉及整個系統物理環境、架構和業務邏輯,要根據情況動態調整,web server允許的最大連線數還受制於作業系統的核心引數設定,通常Windows是2000個左右,Linux是1000個左右

其他屬性配置參考官方文件

資料庫調優

連線數調優

對於Oracle資料庫,預設最大連線數為150,可通過下面的SQL來查詢和修改(DB2 9.7+、MS SQL SERVER 2008+預設不限制連線數)

select count(*) from v$process --當前的連線數

select value from v$parameter where name = 'processes' --資料庫允許的最大連線數
--修改最大連線數,一般設定為1500-3000,重啟資料庫服務後生效:
alter system set processes = 1500 scope = spfile;

索引

索引是什麼?請百度
索引的效能提高測試,參考http://www.cnblogs.com/xwdreamer/archive/2012/05/03/2480449.html
建立索引的一般規則:
1.為查詢條件中的欄位建立索引,通常這些欄位應該為狀態值等字典欄位或日期欄位
2.僅左like('xx%')查詢會使用索引,其他like('%xx%'或'%xx')查詢不會使用索引
3.索引並不是越多越好,索引會降低插入和更新的速度,因為當insert或Update的時候要更新索引
4.巧用唯一索引,確保資料的唯一性

分割槽分表

什麼是分割槽、分表,請自行百度。
1.只有針對大表,分割槽分表才有意義;一般大表是指記錄數在百萬級的,至少也是幾十萬;否則請考慮其他優化方式
2.相對而言,優先考慮分割槽,因為分表需要修改程式碼邏輯
3.常用的分割槽一般為範圍分割槽和列表分割槽

連線池調優

無論是JNDI資料來源,還是DBCP連線池,都有一些連結池引數,這些引數的設定參考如下:
<property name="minPoolSize" value="10"/><!--連線池中保留的最小連線數。-->
<property name="maxPoolSize" value="100"/>  <!--連線池中保留的最大連線數。Default: 15,一般為300以內-->
<property name="initialPoolSize" value="10"/>  <!--初始化時獲取的連線數,取值應在minPoolSize與maxPoolSize之間。過大則啟動過慢 -->
<property name="maxIdleTime" value="60"/><!--最大空閒時間,60秒內未使用則連線被丟棄。若為0則永不丟棄。Default: 0 -->

<property name="acquireIncrement" value="5"/><!--當連線池中的連線耗盡的時候c3p0一次同時獲取的連線數。Default: 3,此數嚴禁過大 -->

功能優化

從功能設計上,避免一次性載入大量資料。遇到一次性載入大量資料的,通過以下問題尋找功能優化方式:

1.       設定預設查詢條件,僅載入部分資料。如對於監測資料的查詢分析,可預設僅查詢當天或當月的資料;

2.       將資料展示使用類似TAB的元素分開,根據使用者操作,採用AJAX分步載入資料

3.       實時性要求不高的資料,不要實時查詢,可快取或者放到Session

程式碼調優

SQL優化

1.       儘量使用join,不要使用子查詢

2.       可能的情況下,儘量使用UNION ALL來代替UNION

小竅門:可使用PL/SQL 或者 SQLServer Management Studio檢視SQL的執行計劃,進而對SQL進行優化。

快取的使用

關於EhCache、Redis的使用,請自行百度。

耗時操作的處理

需求:對某事項進行審批,審批通過後發郵件給提交人。發郵件即為一個耗時操作,如果審批通過後,在當前執行緒中執行發郵件的操作,則會阻塞當前執行緒,直到郵件傳送結束。經驗分享:

耗時操作可以啟動一個新的執行緒執行,避免阻塞當前執行緒(request)

或者將耗時操作僅僅設定一個未執行的狀態,後臺跑一個QZ任務,定時批量執行。

程式碼邏輯調優

1.       避免for 多層巢狀

2.       避免對大陣列的迭代對比,考慮使用Arrays.binarySearch()

靜態檔案優化

靜態檔案優化主要是指對檔案大小的優化。檔案大小往往被很多開發人員忽略,但對於頻寬有限(公網專案)或者硬體裝置(主要是交換機)老舊的環境,檔案大小往往是效能的最大瓶頸。試想一個index.action,所有檔案通過瀏覽器另存之後大小為3M,則100併發,就需要3*100 = 300M的瞬時流量,需要300 * 8 = 2.4Gbps的頻寬才能在1秒內下載完畢(粗算,不科學)

1.       不要引用重複的、沒必要的jscss檔案

2.       對於jscss檔案較大的,需要壓縮

3.       不要使用>100K的圖片

網路優化

測試環境的網路拓撲

需求:某外網系統首頁要求滿足100使用者併發訪問,響應時間<3秒,此首頁所有資原始檔的總大小為1.5M(瀏覽器另存)。如果測試工程師在自己家裡的電腦上用LoadRunner測試,或者在思路公司的內網環境下測試,均不能達標,為什麼?因為家庭頻寬一般<20Mbps,且一般家庭都採用了一些家用路由,如TP-link xx型號等,思路公司內網環境同樣有層層交換機(裝置舊),而且出口眾多(分流很大)造成LoadRunner測試機本身的頻寬不夠,無法承受接收100個使用者的併發流量模擬。結論:
LoadRunner
程式本身的效能測試最好將測試客戶機同伺服器直接連線在一個企業級交換機上,排除網路因素。

頻寬問題

參見上述靜態檔案大小、測試環境的網路拓撲,得出結論:頻寬很重要。要做壓力測試,首選將測試機同伺服器直連到同一個企業級交換機(千兆以上)上。