環境搭建ok後我們開始使用tsung進行性能測試
模板
其實tsung提供了一系列的模板,包括所有tsung支持的服務類型的xml模板
cd /usr/local/tsung/share/doc/tsung/examples/
可以直接拷貝模板xml,稍微修改即可使用
xml文件內容
1. 客戶端
<clients>
<client host="localhost" cpu="4" maxusers="30000"/>
</clients>
- host:客戶端的host地址,需要配置host信息,在上面文章中有說明配置方式,但這裏強調的是即使客戶端開在本機上,Tsung也會通過ssh遠程開啓進程,而且不會使用密碼
- cpu:儘量把cpu的值設得和該主機的CPU數量相等,Tsung保證會把這些進程分配到不同的CPU內核上,上面的例子中定義了一個客戶端,在localhost這臺主機上開4個進程同時發送請求
- maxusers:設置這個客戶端最多可同時虛擬多少個用戶,注意,如果這個數值大於你的ulimit-Sn,則tsung會開多個系統進程來確保這個數值
tsung-1.0.dtd源碼文件中對客戶端參數的定義 tsung-1.0.dtd
<!ELEMENT clients (client+)>
<!ELEMENT client (ip*| iprange) >
<!ATTLIST client
cpu NMTOKEN "1"
type (machine | batch) "machine"
host NMTOKEN #IMPLIED
batch (torque | pbs | lsf | oar) #IMPLIED
scan_intf NMTOKEN #IMPLIED
maxusers NMTOKEN "800"
use_controller_vm (true | false) "false"
weight NMTOKEN "1">
2. 服務端
<servers>
<server host="tsung-dev.test.lluozh.com" port="80" type="tcp" />
</servers>
tsung-1.0.dtd源碼文件中對服務參數的定義 tsung-1.0.dtd
<!ATTLIST server
host NMTOKEN #REQUIRED
port NMTOKEN #REQUIRED
weight NMTOKEN "1"
type (ssl|tcp|udp|erlang|ssl6|tcp6|udp6|bosh|bosh_ssl|websocket|websocket_ssl ) #REQUIRED>
3. 負載配置
tsung有一個概念叫到達階段(arrival phase),它有以下幾個參數:
- 當前階段是第幾個階段(phase)
- 一個階段持續多長時間(duration和unit)
- 在這個階段裏,每多長時間產生多少(虛擬)用戶
<load>
<arrivalphase phase="1" duration="1" unit="minute">
<users arrivalrate="1000" unit="second"/>
</arrivalphase>
<arrivalphase phase="2" duration="2" unit="minute">
<users arrivalrate="10000" unit="second"/>
</arrivalphase>
</load>
這裏定義了2個用戶到達階段(arrival phase)
第一階段的總時長是1分鐘,在這一分鐘裏,每秒鐘會有1000個虛擬用戶來訪問
第二階段的總時長是2分鐘,在這兩分鐘裏,每秒鐘會有10000個虛擬用戶來訪問
- phase:階段,填數字即可,系統會按順序執行,可是設置多個階段組合場景
- duration:持續時段,填數字即可,單位unit="minute"設置,可以是second(秒)、minute(分鐘)、hour(小時)
- arrivalrate:虛擬用戶數,一般最大800(根據機器的性能),實際執行可能超過,也可能達不到(需要根據調試得到最佳參數)
4. 添加會話
所謂會話,就是每個用戶先後做哪些事情,對於HTTP的測試,當然就意味着發請求,收響應
tsung對每個會話會自動管理cookie
<sessions>
<session name="http-example" probability="100" type="ts_http">
<request>
<http url="/api/v1/model?roomId=158589982254376" method="GET" version="1.1"></http>
</request>
<thinktime min="2" max="10" random="true"/>
</session>
</sessions>
在這個例子裏,每個用戶的會話會做兩件事:
- 發送一個HTTP 1.1的GET請求到/,並接收響應
- 收到響應後,sleep(模擬閱讀網頁的時間),時間從2-10秒隨機
websocket請求
此次主要目的是模擬websocket的請求,那根據業務請求包組裝sessions數據如下
<sessions>
<session name="websocket" probability="100" type="ts_http" weight="1">
<request>
<websocket type="connect" path=""/>
</request>
<request subst="true">
<websocket type="message">
{"cmd":"ping","seq":"","data":"","extend":""}
</websocket>
</request>
<thinktime min="1" max="10" random="true"/>
<request>
<websocket type="close"/>
</request>
</session>
</sessions>
此時在服務端並沒有產生對應的數據,查看服務端的日誌,發現服務端並沒有收到消息,因爲數據包的問題,消息直接被網關攔截了
瞭解具體的數據情況,該websocket對處理進行了一層處理
那是否可以直接發送二進制數據呢?
tsung1.7.0版本提供了直接發送binary的數據
<!ELEMENT websocket (#PCDATA | http_header)* >
<!ATTLIST websocket
type (connect | message | close) #REQUIRED
ack (no_ack | parse) #IMPLIED
frame (binary | text) #IMPLIED
origin CDATA ""
subprotocols CDATA ""
path CDATA "/" >
由frame屬性設置binary和text兩種格式
<session name="websocket" probability="100" type="ts_websocket">
<request subst="true"><websocket type="connect" path="/"></websocket>
</request>
<request subst="true">
<websocket type="message" frame="text">080110001a95020a2432336630653432632d323436662d346131312d616533302d3063316333366137303
36332122039323938653065626539323334613162393665333264666437623364333835651a00220e31383831333239363134387474742a003289017b2261757468223a7b227
5736572223a7b2274696d657374616d70223a2231353837343638353237383032222c227369676e6174757265223a22443937433244444133453436453545364434383245394
5384545383441463933222c22746f6b656e223a223862663035636233373630343464343139386661656664336364613439653538227d7d7d3a09756e646566696e65644a1c3
c6769746272616e63683e2f312e322e302e3c676974636f756e743e5004581e</websocket>
</request>
</session>
</sessions>
此時數據可發送至服務端,建立連接connect可以成功,但是未能解析二進制文件,該數據爲text格式
在客戶端進行抓包
tcpdump -i any host xxx.xxx.xxx.xxx or port 8080 -v -n -w dump.pcap
抓取的數據包
TCP握手成功,connect數據包ok,發送出去message的數據包爲文本格式
嘗試修改type爲raw格式發送數據
<sessions>
<session name="websocket" probability="100" type="ts_websocket">
<transaction name="open">
<request subst="true">
<raw data="080110001a95020a2432336630653432632d323436662d346131312d616533302d30633163333661373033633212203932393865306562653932
3334613162393665333264666437623364333835651a00220e31383831333239363134387474742a003289017b2261757468223a7b2275736572223a7b2274696d657374616d
70223a2231353837343638353237383032222c227369676e6174757265223a224439374332444441334534364535453644343832453945384545383441463933222c22746f6b
656e223a223862663035636233373630343464343139386661656664336364613439653538227d7d7d3a09756e646566696e65644a1c3c6769746272616e63683e2f312e322e
302e3c676974636f756e743e5004581e" ack="local"></raw>
</request>
</transaction>
</session>
</sessions>
此時請求又被網關層給攔截
查看使用文檔Tsung
Example with Websocket as a session type:
<request subst="true">
<websocket type="connect" path="/path/to/ws"></websocket>
</request>
<request>
<dyn_variable name="uid" jsonpath="uid"/>
<!-- send data with text frame, default binary-->
<websocket type="message" frame="text">{"user":"user", "password":"password"}</websocket>
</request>
<request subst="true">
<match do="log" when="nomatch">ok</match>
<websocket type="message">{"uid":"%%_uid%%", "data":"data"}</websocket>
</request>
<request>
<websocket type="message" ack="no_ack">{"key":"value"}</websocket>
</request>
<request>
<websocket type="close"></websocket>
</request>
</session>
根據以上請求格式各種修改,均失敗
此後又嘗試修改加服務type爲ssl等方式,均失敗
查看tsung的 issue 信息,沒有相關的解決
查看tsung的安裝包列表
目前使用的tsung-1.7.0版本已是是最新的包,且在2017年更新,此請求只能暫時擱置了,後續看是否可以修改erlang源碼解決該問題或者通過自定義插件的方式實現