投票接口壓測
一、壓測需求:
關於app的投票功能,涉及兩個接口:1、首先是登錄接口,登錄成功提交後,會返回登錄認證用的token值,token值會過期。2,然後投票接口的url中用”?”拼接token值,進行投票
針對投票只能一天10次的限制,經溝通後壓測期間放開,目前可以使用同一個賬號/多個賬號,對一個人進行無限次投票
二、測試腳本分析:
常見的app接口的壓測,關註點是服務器的處理能力時,一般選擇的方式是監聽抓取,可以使用電腦分享熱點,手機連接熱點後,設置靜態ip,使用fiddler監聽指定的端口,
http的請求相對簡單,直接就能抓取到,但本次壓測涉及到的請求為https需要安裝證書配置環境且研發提供了對應的接口文檔,所以可以直接使用loadrunnner構造請求。
三、相關接口:
【涉及到生產環境,故只記錄傳遞的參數,url1表示登錄的url地址,url2表示投票的url地址】
登錄接口:url1
入口參數:JSON格式
{"account":"root-xj","pwd":"meta"}
返回參數:JSON格式
{
"result": "success",
"msg": "操作成功",
"token": "963e5d032e00d559c765c474a18e5bfe302e4c1e",
.....
}
投票接口:url2?token=*****
入口參數:JSON格式
{"userorcomuuId":"18611111111","userorcom":"c1","votecategoryId":"v1"}
返回參數:JSON格式
{"result":"success","msg":"投票成功"}
四、腳本
此次壓測使用的工具是loadrunner,腳本的思路如下:
使用loadrunner自帶的web_custom_request()函數進行post請求體的構造。登錄請求的返回值進行動態關聯獲取,參數化名為getTokenid,將該值傳入到投票請求的url中,進行投票提交。
增加兩個文本檢查點:1)登錄成功的驗證 2)投票成功的驗證
Action() { //動態關聯,根據左右邊界值,獲取tokenid web_reg_save_param("getTokenid","LB=\"token\":\"", "RB=\"", "NotFound=ERROR", LAST); //文本檢查點,判斷是否登錄成功,由於回放response是亂碼,因此直接使用亂碼作為檢查點就可以 web_reg_find("Fail=NotFound", "Text=鎿嶄綔鎴愬姛", LAST); //構造登錄請求,名稱自定義,URL為請求的接口地址,Method為請求用到的方法,body體中為請求用到的json參數,註意轉移字符“\”的使用 web_custom_request("web_custom_request", "URL=https://url1", "Method=POST", "TargetFrame=", "Resource=0", "EncType=application/json", //編碼類型,指定請求頭的content-type互聯網媒體類型;也叫做MIME類型,在Http協議消息頭中,使用Content-Type來表示具體請求中的媒體類型信息。 "Referer=", "Body={\"account\":\"root-xj\",\"pwd\":\"meta\"}", LAST); web_reg_save_param("res", "LB=", "RB=", LAST); //檢查點,驗證是否投票成功 web_reg_find("Fail=NotFound", "Text=鎶曠エ鎴愬姛", LAST); //添加投票的事務 lr_start_transaction("投票"); //構造投票請求的post請求體,尤其註意 EncType=application/json web_custom_request("vote",
"URL=https://url2?token={getTokenid}", "Method=POST", "TargetFrame=", "Resource=0", "Referer=", "EncType=application/json", "Mode=HTML", RAW_BODY_START,
"{\"userorcomuuId\":\"18611111111\",\"userorcom\":\"c1\",\"votecategoryId\":\"v1\"}", 70, RAW_BODY_END, //"Body=\{\"userorcomuuId\":\"18611111111\",\"userorcom\":\"c1\",\"votecategoryId\":\"v1\"\}", LAST); lr_end_transaction("投票", LR_AUTO); lr_output_message(lr_eval_string("{res}")); return 0; }
五、腳本調試遇到的問題
- HTTPS請求報錯
報錯信息:
Action.c(15): Error-27780: [GENERAL_MSG_CAT_SSL_ERROR] connect to host "www.txbzjl.com" failed: [10054] Connection reset by peer [MsgId: MERR-27780]
解決辦法:
Vuser-RuntimeSetting中設置勾選“Winlnet replay instead of Sockets(windows only)”
- HTTP Status 500
報錯信息:
org.codehaus.jettison.json.JSONException: A JSONObject text must begin with ‘{‘ at character 0 of
解決思路:
1) root cause的報錯信息,字面意思是:一個JSON對象必須以“{”開始,錯誤第0個字符。出現這個異常的原因是json串格式不正常,沒有"{"開始或沒有"}"結尾,
仔細檢查下json文件的格式一般就可以解決這個問題。
2) 需要如果在發送請求不加"EncType=application/json",請求頭發出去的默認enctype就是“application/x-www-form-urlencoded”, 窗體數據被編碼為名稱/值對。
3) 在解析流的過程中,首先是將傳遞的字符串使用解析器,進行解析,然後轉換格式為指定的類型:一個是JSONarray一個是jsonObject,出現這種報錯的問題有可能是,
本應當以JSONArray來處理的元素,卻被當做JSONObject來對待,而字符串的形式卻是[],不是以{}的形式存在,導致報錯。
六、壓測中發現的問題
在並發100,加入檢查點,同時投給一個人,持續壓入3w投票數據後,發現手機端顯示的該人的投票數與loadrunner的成功事務數/後臺統計的總投票數,不一致,只有1w多票。
經過分析排查,導致這個問題的原因是,壓測時多線程並發,研發在後臺的投票方法中,沒有加鎖。但是加了鎖以後,在並發使用時,會導致很大程度上的等待,又使用了java多線程處理,
這樣在並發時,一是保證了響應時間,一是保證了數據的準確性。
投票接口壓測