性能測試提早準備及分析

1、測試前準備html

 

一、記錄性能測試時間;java

二、記錄應用服務器、數據庫服務器等CPU、內存等配置狀況;mysql

三、修改tomcat的內存配置和最大鏈接數配置:linux

linux一個進程支持的最大線程數是1000;nginx

(1)tomcat的內存配置:在tomcat的bin/catalina.sh配置中web

JAVA_OPTS='-Xms2048m -Xmx4096m -XX:PermSize=1024M -XX:MaxNewSize=1024m -XX:MaxPermSize=1024m -Dfile.encoding=UTF-8 -Dglobal.config.path=/usr/local/jconfig'
 sql

(2)最大鏈接數配置:tomcat配置文件server.xml數據庫

maxThreads="1000" 最大併發數 後端

minSpareThreads="100"///初始化時建立的線程數瀏覽器

maxSpareThreads="500"///一旦建立的線程超過這個值,Tomcat就會關閉再也不須要的socket線程。

acceptCount="700"// 指定當全部可使用的處理請求的線程數都被使用時,能夠放處處理隊列中的請求數,超過這個數的請求將不予處理

<Connector port="8080" protocol="HTTP/1.1"   
           connectionTimeout="20000"   
           redirectPort="8443" acceptCount="500" maxThreads="600" acceptCount="800" maxSpareThreads="500" minSpareThreads="100"/>  

四、運行LR的機器的配置及性能;

場景設置: 一個Vuser 完成登陸退出操做,執行時間爲5分鐘

result: 最大響應時間與最小響應時間,差距超大(120s,0.7s)

解決辦法: 出現此狀況爲Run-Time settings -->General -->Pacing 沒有配置

五、修改tomcat中web應用的log4j.xml日誌級別爲ERROR,將mysql數據庫的輸出日誌級別改爲ERROR;

mysql> show variables like '%log_error%';
+---------------+--------------------------------+
| Variable_name | Value                          |
+---------------+--------------------------------+
| log_error     | /tmp/DB-Server.localdomain.err |

六、修改Linux的訪問最大進程數

linux用戶的最大進程數 ulimit須要修改,默認是1024,修改命令:ulimit -n 10240

七、安裝數據庫和linux相關監控工具;

(1)淘寶有一款開源監控工具orzdba

代碼SVN地址:http://code.taobao.org/p/orzdba/src/trunk/

八、修改ngnix配置

若是須要獲得請求處理的時間,須要在nginx log 裏面加上$request_time,下面是個人log_format

nginx.conf

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '

                              '$status $body_bytes_sent $request_body "$http_referer" '

                              '"$http_user_agent" "$http_x_forwarded_for" "$request_time"';

修改以後重啓nginx,查看nginx log的時候,就能看到nginx處理請求所花的時間了,這個時間基本就是後端所花的時間,因此能夠根據這個字段來獲得響應慢的請求。

9.使用性能監控工具:zabbix、newrelix,國內的監控寶均可以考慮

2、性能測試分析

一、性能測試運行時應用數據庫查看

例如:讀寫狀況、併發數狀況、數據庫緩存狀況、內存使用狀況、cpu使用狀況、網絡狀況

監控工具:zabbix 

查看如下命令:查看MYSQL一些狀態,有沒有一些鏈接一直佔用着;是否佔用鏈接數達到限制;

(1)鏈接數查看命令:

while true; do mysqladmin -uroot -p'test@jushi!123' processlist|wc -l;sleep 3; done

(2)MySQL服務器的鏈接總數: show status like '%connect%';

Aborted_clients 因爲客戶沒有正確關閉鏈接已經死掉,已經放棄的鏈接數量。
Aborted_connects 嘗試已經失敗的MySQL服務器的鏈接的次數。 
Connections 試圖鏈接MySQL服務器的次數。

Max_used_connections 同時使用的鏈接的最大數目。 

Slow_queries 要花超過long_query_time時間的查詢數量。 
Threads_connected 當前打開的鏈接的數量。 
Threads_running 不在睡眠的線程數量。 

(3) 查看當前正在進行的進程,對於有鎖表等狀況的排查頗有用處

SHOW PROCESSLIST; 默認顯示前100條 
SHOW FULL PROCESSLIST; 顯示全部

command列:顯示當前鏈接的執行的命令,通常就是休眠(sleep),查詢(query),鏈接(connect)。 

(4) 顯示當前mysql狀態:mysqladmin -u -p -h status   

[root@db ~]# mysqladmin -uroot -p -hlocalhost status

Enter password:

Uptime: 14604445  Threads: 208  Questions: 34034734  Slow queries: 179  Opens: 12553  Flush tables: 3  Open tables: 977  Queries per second avg: 2.330

(5)顯示mysql的其餘狀態:mysqladmin -u -p -h extended-status

[root@db ~]# mysqladmin -uroot -p -hlocalhost extended-status
Enter password: 
+------------------------------------------+--------------+
| Variable_name                            | Value        |
+------------------------------------------+--------------+
| Aborted_clients                          | 53041        |
| Aborted_connects                        | 163          |
| Connections                              | 1116157      |
…… 略
| Threads_connected                        | 206          |
| Threads_created                          | 633          |
| Threads_running                          | 1            |
| Uptime                                  | 14604661    |
| Uptime_since_flush_status                | 14604661    |
+------------------------------------------+--------------+

(6)慢查詢show global status like '%slow%';  

  1. mysql> show variables like '%slow%';  
  2. +------------------+-------+  
  3. | Variable_name    | Value |  
  4. +------------------+-------+  
  5. | log_slow_queries | OFF   |  
  6. | slow_launch_time | 2     |  
  7. +------------------+-------+  

(7)鏈接數

  1. mysql> show variables like 'max_connections';  
  2. +-----------------+-------+  
  3. | Variable_name   | Value |  
  4. +-----------------+-------+  
  5. | max_connections | 500   |  
  6. +-----------------+-------+  
  7.   
  8. mysql> show global status like 'max_used_connections';  
  9. +----------------------+-------+  
  10. | Variable_name        | Value |  
  11. +----------------------+-------+  
  12. | Max_used_connections | 498   |  
  13. +----------------------+-------+  

設置的最大鏈接數是500,而響應的鏈接數是498
max_used_connections / max_connections * 100% = 99.6% (理想值 ≈ 85%)

http://blog.csdn.net/zhangliangzi/article/details/51884863

(8)進程使用狀況

  1. mysql> show global status like 'Thread%';  
  2. +-------------------+-------+  
  3. | Variable_name     | Value |  
  4. +-------------------+-------+  
  5. | Threads_cached    | 31    |  
  6. | Threads_connected | 239   |  
  7. | Threads_created   | 2914  |  
  8. | Threads_running   | 4     |  
  9. +-------------------+-------+  

若是咱們在MySQL服務器配置文件中設置了thread_cache_size,當客戶端斷開以後,服務器處理此客戶的線程將會緩存起來以響應下一個客戶而不是銷燬(前提是緩存數未達上限)。Threads_created表示建立過的線程數,若是發現Threads_created值過大的話,代表 MySQL服務器一直在建立線程,這也是比較耗資源,能夠適當增長配置文件中thread_cache_size值,查詢服務器 thread_cache_size配置:

(9)表鎖狀況

  1. mysql> show global status like 'table_locks%';  
  2. +-----------------------+---------+  
  3. | Variable_name         | Value   |  
  4. +-----------------------+---------+  
  5. | Table_locks_immediate | 4257944 |  
  6. | Table_locks_waited    | 25182   |  
  7. +-----------------------+---------+  

Table_locks_immediate 表示當即釋放表鎖數,Table_locks_waited表示須要等待的表鎖數,若是 Table_locks_immediate / Table_locks_waited > 5000,最好採用InnoDB引擎,由於InnoDB是行鎖而MyISAM是表鎖,對於高併發寫入的應用InnoDB效果會好些.

(10) TPS(每秒事務量) 

TPS = (Com_commit + Com_rollback) / seconds 

mysql > show global status like 'Com_commit'; 

mysql > show global status like 'Com_rollback'; 

(11)Query Cache命中率 

mysql> show status like 'Qcache%'; 

Query_cache_hits = (Qcahce_hits / (Qcache_hits + Qcache_inserts )) * 100%; 

(12)查看linux實時內存及CPU狀態:vmstat 3 50 

二、性能測試運行時應用服務器查看

應用服務器:tomcat內存使用狀況、CPU使用狀況、讀寫狀況、網絡流量使用狀況等;有沒有dump日誌

(1)查看linux內存:vmstat 3 50 

98.7% id 空閒CPU百分比

top

進入top以後,按數字鍵1,你就能看到多個CPU了。

%CPU=(進程的生命週期中佔用CPU的時間)*100/(進程的生命週期表明的時間長度)
好比一個進程的生命週期的時間長度是1000s,而後在這1000s內佔用CPU的時間是500s,那麼
%CPU=500*100/1000=50
即最後的結果表示50%

load average: 0.06, 0.60, 0.48 系統負載,即任務隊列的平均長度。

三個數值分別爲 1分鐘、5分鐘、15分鐘前到如今的平均值。

Cpu(s): 0.3% us 用戶空間佔用CPU百分比

1.0% sy 內核空間佔用CPU百分比

0.0% ni 用戶進程空間內改變過優先級的進程佔用CPU百分比

98.7% id 空閒CPU百分比

0.0% wa 等待輸入輸出的CPU時間百分比

(2)查看硬盤存儲

df -h

(3)查看java進程實時狀況

JVM進程情況工具:jps -m

查看19434的線程快照:jstack -l 19434

輸出java堆棧信息打印日誌:jstack 19434 >test.log

獲取dump日誌:jmap -dump:format=b,file=heap.dump 19434

用如下命令查看dump日誌,會轉成html:jhat {dump_file} 

啓動成功:瀏覽器訪問:http://192.168.1.50:7000/便可查看;

 

(4)因爲日誌過多致使系統存儲空間不足;

查看命令:df -h

(2)獲取tomcat日誌、數據庫日誌、ngnix日誌並分析日誌錯誤地方;


 

四、LR報告:

(1)LR中的最大響應時間參考價值不高;

(2)LR平均響應時間average transaction response time(整個場景測試中的平均響應時間)

採樣時間可進行配置

Summary是按整個場景的時間來作平均的,最大最小值,也是從整個場景中取出來的。
而平均事務響應時間圖裏,是按頻率來取值。這兩個值沒有什麼可比性。也沒有什麼關係。
只是一堆數據的不一樣計算方法。在取樣時間內,有可能比summary裏的高,有可能低,有可能持平。

(3)各參數說明

關於事務狀況的總結
 Total Passed(事務的總經過數)
 Total Failed(事務的總失敗數)
 Total Stopped(事物的總中止數) 手工事務中沒有此項
 SLA Status(SLA狀態)在SLA中的最終結果
 Minimum(事務最小時間)
 Average(事務平均時間)
 Maximum(事務最大時間)

Average Transaction Response Time
 Transactions per Second  TPS吞吐量
 Transaction Performance Summary 

Throughput  帶寬使用,該值越小說明系統對帶寬依賴越小,此處使用的單位是字節(大B),百兆帶寬指的是小b(位)

Connections per second  每秒鏈接數,此值與服務器的鏈接池大小有關,其中包括兩個值,中斷的鏈接數,新建的鏈接
數,當服務器中鏈接池用完時,服務器會返回504錯誤。

 

3、優化過程

一、問題一:

原代碼

@Transactional(readOnly = false, propagation = Propagation.REQUIRES)
public  String getFuneralOrderNoSeq() throws ZdnstException {
   String seq = "";
   try {
      int i=this.updateAddSeqNumBySeqId(Constants.SYS_FUNERAL_ORDERNO_SEQ);
      if(i==0){
         SysSeq sysSeq=new SysSeq();
         sysSeq.setSysSeqId(Constants.SYS_FUNERAL_ORDERNO_SEQ);
         sysSeq.setSeq("1");
         sysSeqMapper.insert(sysSeq);
      }
      // 獲取用戶帳號
      SysSeq sysSeq = sysSeqMapper.selectByPrimaryKey(Constants.SYS_FUNERAL_ORDERNO_SEQ);
      // 從新插入序列號
      if(Integer.parseInt(sysSeq.getSeq())==9999){
         sysSeq.setSeq("1");
         sysSeq.setCreateTime(DateUtils.getCurTimestamp());
         sysSeqMapper.updateByPrimaryKey(sysSeq);
      }
      String fSeq=this.gengercode(4, sysSeq.getSeq(),DateUtils.DATE_FORMAT_YYYYMMDD);
      return fSeq;
   } catch (ZdnstException e) {
      //打印服務層異常詳情,注意第二個參數必須傳打印異常堆棧
      logger.error(Constants.EX_SERVICE_EXCEPTION + BaseCode.getDetailMsg(e), e);
      //必須拋出通知調用者
      throw new ZdnstException(e.getCode(),e.getMessage());
   } catch (Exception e) {
      //打印服務層異常詳情,注意第二個參數必須傳打印異常堆棧
      logger.error(Constants.EX_SERVICE_EXCEPTION + BaseCode.getDetailMsg(e), e);
      //封裝爲服務層異常110網絡超時後再拋出,必須拋出通知調用者
      throw new ZdnstException(BaseCode.ERROR_CODE110,e.getMessage());
   }
}

修改位置:將這一塊獨立成一個新事物,具體修改是:將propagation = Propagation.REQUIRES修改爲propagation = Propagation.REQUIRES_NEW

二、問題二

未完,待續……

 

 

 

性能測試調優應該注意的要點:

  • 要點1: 在應用系統的設計開發過程當中,應始終把性能放在考慮的範圍內。
  • 要點2: 肯定清晰明確的性能目標是關鍵。
  • 要點3: 必須保證調優後的程序運行正確。
  • 要點4: 系統的性能更大程度上取決於良好的設計,調優技巧只是一個輔助手段。
  • 要點5: 調優過程是迭代漸進的過程,每一次調優的結果都要反饋到後續的代碼開發中去。
  • 要點6: 性能調優不能以犧牲代碼的可讀性和可維護性爲代碼。
相關文章
相關標籤/搜索