響應時間=網絡傳輸時間+服務器響應時間+網絡傳輸時間+前端渲染時間
TPS:是指每秒通過事務數,直接反應系統性能的指標,該值越大時,系統性能會比較好,當然每個系統都會有它的上線
每秒點擊數:每秒點擊數代表用戶每秒向WEB服務器提交的HTTP請求書。
吞吐量:單位時間內系統處理的請求數。
資源利用率:cpu:系統CPU 用戶CPU
Load Average:指一段時間內cpu正在處理和等待cpu處理的任務,也就是cpu使用隊列的長度的統計信息
Memroy:短時間內可用內存越來越少,不代表一定有內存泄露或溢出。
IO:與磁盤的交互,重點關注交互頻率,磁盤隊列長度。
併發測試:併發數=pv/pv Time * 頁面鏈接次數 * HTTP響應時間 * 因數 /web 服務器數量。
Tomcat 與 JVM優化
<!--
tomcat/conf/server.xml
系統日誌:現在日誌分析是越來越重要的性能測試需求獲取手段,大型公司越來越多重視日誌分析,數據挖掘中,很重要的一點是對日誌進行分析,然後分析用戶使用行爲,通過日誌分析,可以幫助性能測試人員快速獲取系統性能參數,如併發量,響應時間,業務分部情況等,日誌分析也能用於測試人員進行性能預警和容量規劃工作,一般的WEB Server 有兩部分日誌:一是運行 中日誌,它主要紀錄的一些信息,尤其是一些異常錯誤日誌信息;二是訪問日誌信息,他記錄訪問的時間、ip地址、訪問的資料等相關信息。爲了獲取系統性能測試的需求,可以分析WEB Server的訪問日誌以瞭解更多真實負載和主要的業務場景,將下面的日誌打開,去掉註釋即可,其中directory試生產目錄,tomcat的安裝目錄catalina作爲當前目錄,pattern表示日誌生產的格式,common是tomcat提供的一個標準設置格式,期具體表達式%h %l %u %t %r %s %b
-->
<!--
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>
-->
Tomcat的運行是基於JAVA的虛擬機。SUN的JVM動態庫有client和Server兩個版本,分別對桌面應用和服務器應用做了相應的優化,client版本加載速度比較快,server版本加載速度比較慢但運行起來比較快。
在命令行輸入java -version 可以看到jvm目前配置的那個版本。如果要修改jvm的版本可更改默認java.exe調用的jvm.dll,這個由jvm.cfg決定。編輯%JAVA_HOME%jre/leb/i386/jvm.cfg文件,裏面第一行寫的是-client(默認就是client版本),把第二行的-server KNOWN放到第一行,重啓tomcat,命令java -version.
表明Tomcat修改使用Server版本的jvm,讀者可進行比對測試,對比一下client版本的JVM和Server版本性能差異,從而決定採用哪個版本的JVM。
tomcat與內存泄露
tomcat默認內存可以使用的內存爲128MB(不同的版本有所區別),在較大型的應用項目中,這點內存是不夠的,需要調大,否則很容易出現"out of memery"的問題。
在Linux下,修改配置文件{tomcat_home}/bin/catalina.sh , 增加如下設置。
JAVA_OPTS='-Xms【初始化內存大小】 -Xmx【可以使用內存大小】'
需要根據服務器可用的內存把這
另外,對於SUN的JVM,MaxpermSize 參數的調整比較重要。PermSize的大小決定了保持對象(類、方法)的大小,如果碰到"OutOfMemoryError:PermGen"的錯誤提示,應該考慮到調整這個參數的大小,SUM JVM默認保留64MB作爲PermSize大小
maxThreads:鏈接線程數監控與調整
可以通過修改Tomcat安裝目錄的conf文件夾中的配置文件server.xml文件來調整tomcat最大鏈接線程數。maxThreads是最大併發線程數,如果同時的併發請求量超過這個值,tomcat也不會再增加線程,這是併發請求進入隊列,增加maxThreads的值可以加大tomcat的併發處理能力,但是設置過高的maxThreads值也會對性能帶來影響,佔用過多的系統資源,甚至造成tomcat崩潰。
當maxThreads設置比較小時,tomcat處理請求的速度有所下降,同時也需要設置最大併發請求數
**一般web服務器允許的最大鏈接數還受限制於操作系統內核參數設置,通常linux是1000個左右,在centos中可以用一下命令查看Socket最大連接數: ulimit -a
其中的open files是允許打開的最大文件數,centos默認是1024
修改vi /etc/security/limits.conf 配置文件 ,將文件數設置爲32768,在配置文件中添加:
* soft nofile 32768
* hard nofile 32768
重啓系統
acceptCount:最大排隊的設置
acceptCount是指當所有線程都已經被用於處理請求時,允許多少新的連接請求進入排隊隊列等候處理,當隊列滿時,任何新的請求都將被拒絕,默認設置爲1000
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
acceptCount="2000"
maxThreads="800"
redirectPort="8443" URIEncoding="UTF-8"/>
應用代碼性能診斷分析
1、內存泄露診斷分析
程序代碼中,與內存有關的問題可以分爲兩大類:內存訪問錯誤和內存使用錯誤
內存訪問錯誤包含讀內存錯誤和寫內存錯誤,讀內存錯誤可能讓程序模塊返回意想不到的結果,從而導致後續的程序模塊運行異常。
內存使用錯誤主要指程序模塊申請的內存沒有正確釋放,系統可用內存逐漸減少,是程序運行逐漸減慢,直至停止。
2、代碼書寫問題導致內存泄露
一般我們常說內存泄露指的是堆內存的泄露,堆內存是指程序從堆中分配的,大小任意的(內存塊的大小可以再程序運行期決定)使用完後必須顯示釋放的內存。
一般使用:malloc , calloc ,realloc , new ,等函數從堆中分配到一塊內存,使用完後,城西南 必須負責相應的調用free和delete釋放內存塊,否則,這塊內存就不能被內存再次使用,我們就說這塊內存泄露了。
造成內存泄露的原因很多,最常見的有以下幾種。
分配完內存忘記回收,
程序寫法有問題,造成沒有辦法回收
某些API函數的使用不正確,造成內存泄露
沒有及時釋放
JVM內存泄露診斷分析--JVM原理與監控
PermGen是JVM自用的區域,是內存的永久保護區,用於存放反射代理和Class,在Class被裝載時會被放到PermGen中
JVM啓動參數介紹
JVM啓動時允許加載指定的參數,如果參數指定不恰當,可能會對JVM性能造成較大的影響
Xmn:Eden Generation的Heap大小,一般設置爲Xmx的1/3 或 1/4
Xmx:設置JVM Heap大小最大值,這裏的heap= NEW Generation+Old Generation,但不包括PermGen。
Xms:設置JVM Heap大小初始值
XX:NewRatio :New/Old 的大小比率
XX:NewSize : New Generation Heap的大小
XX:MaxNewSize :可以通過NewRatio 和 -Xmx計算得到
XX:SurvivorRatio : Eden/Survivor Space大小比率
XX:PermSize : PermGen的初始值
XX:MaxpermSize: PermGen最大值
Xss:設置每個線程的Stack大小
XX:+UseParNewGc:表示多CPU下縮短Minor Gc的時間
XX:+UseParallelGc :設置後可以使用並行清除收集器(多CPU)
XX:+ParallelGcThreads:可用來增加並行度(多CPU)
XX:+AggressiveOpts :是否允許激活最近的實驗性性能調整
XX:-Xnoclassgc:是否允許類垃圾收集,默認設置時允許類GC
Servlet 常見性能問題分析與優化
Servlet是J2EE架構中重要的組成部分,Servlet可以生成動態的WEB頁面,它是客戶端請求(web瀏覽器或其他HTTP客戶端程序)與服務器響應(HTTP服務器上的數據庫或應用程序)的中間層
Servlet壓縮輸出
http壓縮可以大大提高瀏覽器的速度,它的原理是:在客戶端請求網頁後,從服務器端將網頁文件壓縮,再下載到客戶端,由客戶端的瀏覽器負載壓縮後在解析呈現,HTTP壓縮大概可以節省40%左右的流量。
public void doGet(HttpServletRequest request ,HttpServletResponse response) throws IOException , ServletException{
String c = request.getParameter("c");
if("c".equals(c)){
response.setHeader("Content-Encoding","gzip");
compressionResponse cResponse = new CompressionResponse(response);
response.setContentTyPe("text/plain");
final OutputStream out = cResponse.getOutputStream();
for(int i=0;i<1000;i++){
out.write(UUID.randomUUID().toString().getBytes());
out.flush();
}
out.close();
}
else{
response.setContentTyPe("text/plain");
PrintWriter out = response.getWrite();
for(int i=0;i<1000;i++){
out.print(UUID.randomUUID().toString().getBytes());
out.flush();
}
out.close();
}
}