Tsung筆記之插件編寫篇

前言

Tsung對具體協議、通道的支持,一般以插件形式提供接口,接口不是很複雜,插件也很容易編寫,支持協議多,也就不足爲怪了。

下面首先梳理一下當前Tsung 1.6.0所有內置插件,然後爲一個名稱爲Qmsg的私有二進制協議編寫插件, 運行Qmsg服務器端程序,執行壓力測試,最後查看測試報告。

已支持插件梳理

Tsung 1.6.0支持的協議很多,簡單梳理一下:

Tsung Controller  Support Plugins V2-1

  • 壓測的協議首先需要支持xml形式配置,配置內容需要 tsung_config_protocolname 模塊解析
    • 存放在tsung_controller目錄下
  • 其次是tsung client端也要插件 ts_protocolname 模塊支持數據操作
    • 存放在tsung目錄下
  • 同時在tsung項目examples目錄下也給出了已支持協議配置簡單示範xml文件

已經支持協議簡單說明:

  1. amqp,Advanced Message Queuing Protocol縮寫,只要支持高級消息隊列協議的應用,都可以用來做壓測,比如RabbitMQ,ActiveMQ等
  2. http,基本協議,構建於HTTP協議之上的,還有類似於BOSH,WebDav等上層業務協議
  3. jabber,也稱之爲XMPP,支持的相當豐富,除了TCP/SSl,還可以通過Websocekt進行傳遞
  4. raw,針對原始類型消息,不做編解碼處理,直接在TCP / UDP / SSL等傳輸層中傳遞,這個對部分私有協議,比較友好,不用寫單獨的編解碼處理,直接透傳好了
  5. shell,針對LInux/Unix終端命令調用進行壓測,這種場景比較小衆
  6. fs,filesystem縮寫,針對文件系統的讀寫性能進行壓測
  7. job,針對任務調度程序進行的壓測,比如PBS/torqueLSF、OAR等

Tsung插件工作機制

粗一點來看Tsung插件的工作流程(點擊可以看大圖):

tsung_qmsg_flo

放大一些(引用 hncscwc 博客圖片,相當贊!):

爲什麼要編寫插件

Tsung針對通用協議有支持,若是私有或不那麼通用的協議,就不會有專門的插件支持了,那麼可選的有兩條路子:

  • 使用raw模式發送原始消息,需要自行組裝
  • 自己編寫插件,靈活處理編解碼

既然談到了插件,我們也編寫一個插件也體驗一下編寫插件的過程。

Qmsg協議定義

假設一個虛擬場景,打造一個新的協議Qmsg,二進制格式組成:

qmsg_protoco

這種隨意假象出來的格式,不妨稱作爲qmsg(Q可愛形式的message)協議,僅作爲Demo演示而存在。簡單場景:

  • 用戶發言,包含用戶id和發言內容
    • User ID,32位自然數類型
    • 發言爲文字內容,字符串形式,長度不固定
    • 組裝後的請求體爲二進制協議格式
    • PocketLen:**##UserId + UserComment##**
  • 服務器端返回用戶ID和一個幸運數字(32位表示)
    • PocketLen:**##UserId + RandomCode##**

爲了卡哇伊一些,多了一些點綴的“**####**”符號。

編寫一個完整插件

這裏基於Tsung 1.6.0版本構建一個Qmsg插件,假定你懂一些Erlang代碼,以及熟悉Tsung一些基本概念。

0. 創建一個項目

要創建Tsung的一個Qmsg插件項目,雖沒有固定規範,但按照已有格式組織好代碼層級也是有必要的。

├── include
│   └── ts_qmsg.hrl
├── src
│   ├── tsung
│   │   └── ts_qmsg.erl
│   └── tsung_controller
│       └── ts_config_qmsg.erl
└── tsung-1.0.dtd

1. 創建配置文件

Tsung的壓測以xml文件驅動,因此需要界定一個Qmsg插件形式的完整會話的XML呈現,比如:

<session probability="100" name="qmsg-demo" type="ts_qmsg">
    <request>
      <qmsg uid="1001">Hello Tsung Plugin</qmsg>
    </request>

    <request>
      <qmsg uid="1002">This is a Tsung Plugin</qmsg>
    </request>
</session>
  • ts_qmsg,會話類型所依賴協議模擬客戶端實現
  • <qmsg uid="Number">Text</qmsg> 定義了qmsg會話可配置形式,內嵌在request元素內
  • uid爲屬性

此時,你若直接在xml文件中編輯,會遇到校驗錯誤。

2. 更新DTD文件

Tsung的xml文件依賴tsung-1.0.dtd文件進行校驗配置是否有誤,需要做對DTD文件做修改,以支持所添加新的協議。

tsung-1.0.dtd項目中,最小支持:

  1. session元素type屬性中添加上 ts_qmsg
  2. request元素處添加 qmsg : <!ELEMENT request ( match*, dyn_variable*, ( http | jabber | raw | pgsql | ldap | mysql |fs | shell | job | websocket | amqp | mqtt | qmsg) )>
  3. 添加qmsg元素定義:
<!ELEMENT qmsg (#PCDATA) >
<!ATTLIST qmsg
    uid         CDATA   "0"
    ack         (local | no_ack | parse) #REQUIRED
    >

完整內容,可參考tsung_plugin_demo/tsung-1.0.dtd文件。

3. 頭文件 include/ts_qmsg.hrl

頭文件include/ts_qmsg.hrl定義數據保存的結構(也稱之爲記錄/record):

-record(qmsg_request, {
          uid,
          data
         }).

-record(qmsg_dyndata, {
          none
         }
       ).
  1. qmsg_request: 存儲從xml文件解析的qmsg請求數據,用於生成壓力請求
  2. qmsg_dyndata: 存儲動態參數(當前暫未使用到)

4. XML文件解析

ts_config_qmsg.erl文件,用於解析和協議Qmsg關聯的配置:
- 只需要實現parse_config/2唯一方法
- 解析xml文件中所配置Qmsg協議請求相關配置
- 被ts_config:parse/1在遇到Qmsg協議配置時調用

備註:

  1. 若要支持動態替換,需要的字段以字符串形式讀和存儲

5. ts_qmsg.erl

ts_qmsg.erl模塊主要提供Qmsg協議的編解碼的完整動作, 以及當前協議界定下的用戶會話屬性設定。

首先需要實現接口ts_plugin規範定義的所有需要函數,定義了參數值和返回值。

-behavior(ts_plugin).

...

-export([add_dynparams/4,
         get_message/2,
         session_defaults/0,
         subst/2,
         parse/2,
         parse_bidi/2,
         dump/2,
         parse_config/2,
         decode_buffer/2,
         new_session/0]).

相對來說,核心爲協議的編解碼功能:

  • get_message/2,構造請求數據,編碼成二進制,上層ts_client模塊通過Socket連接發送給目標服務器
  • parse/2,(當對響應作出校驗時)從原始Socket上返回的數據進行解碼,取出協議定義業務內容

這部分代碼可以參考 tsung_plugin_demo/src/tsung/ts_client.erl 文件。

6. 如何編譯

雖然理論上可以單獨編,生成的beam文件直接拷貝到已經安裝的tsung對應目錄下面,但實際上插件編寫過程中要依賴多個tsung的hrl文件,這造成了依賴路徑問題。採用直接和tsung打包一起部署,實際操作上有些麻煩,

爲了節省體力,使用一個shell腳本 - build_plugin.sh,方便快速編譯、部署:

# !/bin/bash

cp tsung-1.0.dtd $1/
cp include/ts_qmsg.hrl $1/include/
cp src/tsung_controller/ts_config_qmsg.erl $1/src/tsung_controller/
cp src/tsung/ts_qmsg.erl $1/src/tsung/

cd $1/
make uninstall
./configure --prefix=/usr/local
make install

這裏指定安裝Tsung的指定目錄爲/usr/local,可以根據需要修改

需要提前準備好tsung-1.6.0目錄:

wget http://tsung.erlang-projects.org/dist/tsung-1.6.0.tar.gz
tar xf tsung-1.6.0.tar.gz

在編譯Qmsg插件腳本時, 指定一下tsung-1.6.0解壓後的路徑即可:

sh build_plugin.sh /your_path/tsung-1.6.0

後面嘛,就等着自動編譯和安裝唄。

啓動Qmsg協議的壓測

1. 首先啓動Qmsg服務器端程序

既然有壓測端,就需要一個Qmsg協議處理的後端程序qmsg_server.erl,用於接收客戶端請求,獲得用戶ID值之後,生成一個隨機數字,組裝成二進制協議,然後發給客戶端,這就是全部功能。

這個程序,簡單一個文件,在 tsung_plugin_demo目錄下面,編譯運行, 默認監聽5678端口:

erlc qmsg_server.erl && erl -s qmsg_server start

另外,還提供了一個手動調用接口,方便在Erlang Shell端調試:

%% 下面爲
qmsg_server:sendmsg(1001, "這裏是用戶發言").

啓動之後,監聽地址 *: 5678

源碼見:tsung_plugin_demo/qmsg_server.erl

2. 編寫Qmsg壓測XML配置文件

因爲是演示示範,一臺Linxu主機上就可以進行了:

  • 連接本機的 127.0.0.1:5678
  • 最多產生10個用戶,每秒產生1個,壓力負載設置的很低
  • 兩個不同類型會話,比重10% + 90% = 100%
  • qmsg-subst-example會話使用了用戶ID個和用戶發言內容自動生成機制
<tsung loglevel="debug" dumptraffic="false" version="1.0">
  <clients>
    <client host="localhost" use_controller_vm="true"/>
  </clients>

  <servers>
    <server host="127.0.0.1" port="5678" type="tcp"/>
  </servers>

  <load>
    <arrivalphase phase="1" duration="1" unit="minute">
      <users maxnumber="10" interarrival="1" unit="second"/>
    </arrivalphase>
  </load>

  <sessions>
    <session probability="10" name="qmsg-example" type="ts_qmsg">
      <request>
        <qmsg uid="1001" ack="parse">Hello Tsung Plugin Qmsg!</qmsg>
      </request>
    </session>
    <session probability="90" name="qmsg-subst-example" type="ts_qmsg">
      <setdynvars sourcetype="random_number" start="3" end="32">
        <var name="random_uid"/>
      </setdynvars>
      <setdynvars sourcetype="random_string" length="13">
        <var name="random_txt"/>
      </setdynvars>
      <request subst="true">
        <qmsg uid="%%_random_uid%%" ack="parse">Haha : %%_random_txt%%</qmsg>
      </request>
      <thinktime value="6"/>
      <request subst="true">
        <qmsg uid="%%_random_uid%%" ack="parse">This is a Tsung Plugin</qmsg>
      </request>
    </session>
  </sessions>
</tsung>

這部分內容,請參考 tsung_plugin_demo/tsung_qmsg.xml 文件。

3. 執行壓力測試

當Qmsg的壓力測試配置文件寫好之後,可以開始執行壓力測試了:

tsung -f tsung_qmsg.xml start

其輸出:

tarting Tsung
Log directory is: /root/.tsung/log/20160621-1334
[os_mon] memory supervisor port (memsup): Erlang has closed
[os_mon] cpu supervisor port (cpu_sup): Erlang has closed

其中, 其日誌爲:/root/.tsung/log/20160621-1334

4. 查看壓測報告

進入其生成壓測日誌目錄,然後生成報表,查看壓測結果哈:

cd /root/.tsung/log/20160621-1334

/usr/local/lib/tsung/bin/tsung_stats.pl

echo "open your browser (URL: http://IP:8000/report.html) and vist the report now :))"
/usr/bin/python -m SimpleHTTPServer

嗯,打開你的瀏覽器,輸出所在服務器的IP地址,就可以看到壓測結果了。

小結

以上代碼已經放入github倉庫:https://github.com/weibomobile/tsung_plugin_demo

實際業務的私有協議內容要比上面Demo出來的Qmsg複雜的多,但其私有協議插件編寫,如上面所述幾個步驟,按照規範編寫,單機測試,然後延伸到分佈式集羣,完整流程都是一致的。

嗯,搞定了插件,就可以對系統愉快地進行壓測了 :))

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章