接到一個應用測試,應用實現主要使用websocket保持長連接,使用protobuf格式交換數據,用途爲發送消息,須要咱們測試評估性能,初步評估須要測試長連接數、峯值消息數以及長期運行穩定性python
總體需求不難,主要困難是第一次接觸websocket和protobuf,同時也沒有現成的腳本能夠使用,jmeter原生也不支持websocket協議,須要安裝插件支持,protobuf格式也須要從新編譯大包使用web
萬里長征第一步,先開發測試腳本,因爲目前一直在使用python開發,評估項目的性能要求,不須要嚴格性能指標,因此直接使用python做爲開發語言編寫腳本,主要實現腳本以下json
入口主文件,mulitprocess.py,多進程發起創建連接服務器
1 # -*- coding: utf-8 -*- 2 # @Author : monleylu 3 # @Time : 2018/7/5 12:22 PM 4 5 from multiprocessing import Process,Pool 6 import os 7 from data import user 8 from protobufcon import ProtoService 9 import tnlog,logging 10 11 def consumer(host,port,username): 12 logging.error('啓動子進程: %s...' % (os.getpid())) 13 kwargs = {"host": host, "port": port, "username": username } 14 pro=ProtoService(**kwargs) 15 pro.startWebsocket() 16 17 18 def consumer2(*args,**kwargs): 19 logging.error('啓動子進程: %s...' % (os.getpid())) 20 pro = ProtoService(**kwargs) 21 pro.startWebsocket() 22 23 24 25 if __name__ =="__main__": 26 logging.error('啓動主進程 %s.' % os.getpid()) 27 28 p = Pool(450) 29 for i in range(450): 30 #第一種傳參數方法 31 # p.apply_async(consumer, args=("11.31.60.10",8880,user.pop(),)) 32 33 #第二種傳參數方法 34 kw={"host": "11.31.60.10", "port": 8880, "username": user.pop()} 35 p.apply_async(consumer, args=(),kwds=kw) 36 37 logging.error('Waiting for all subprocesses done...') 38 39 p.close() 40 p.join() 41 logging.error('All subprocesses done.')
實現代碼,protobuffun.py,主要負責發送、接收消息websocket
1 # -*- coding: utf-8 -*- 2 # @Author : monleylu 3 # @Time : 2018/7/5 12:15 PM 4 5 import protoinfo.msg_pb2 as msgpb2 6 import websocket,json,datetime 7 import json 8 try: 9 import thread 10 except ImportError: 11 import _thread as thread 12 import tnlog,logging 13 from data import user 14 class ProtoService: 15 16 def __init__(self,*,host="10.30.66.11",port=8886,username="monleylu"): 17 self.host=host 18 self.port=port 19 self.username=username 20 21 def on_message(self,ws, message): 22 msg2 = msgpb2.Msg() 23 msg2.ParseFromString(message) 24 logging.error("用戶:{} 收到消息,類型:{},內容:{}".format(self.username,msg2.method,msg2.data)) 25 if msg2.method == "login": 26 b=msg2.data 27 c=json.loads(b) 28 self.sendprotobuf(ws,"serve_get",{'uc_id':c["uc_id"],'boxReadFlag':'0','boxArriveFlag':'0','boxCollectFlag':'0'}) 29 30 def on_error(self,ws, error): 31 logging.error("發生異常:{}".format(error)) 32 33 def on_close(self,ws): 34 ws.close() 35 logging.error("### closed ###") 36 37 38 # def wrapp(username): 39 # def w(*args,**kwargs): 40 41 42 def on_open(self,ws): 43 self.sendprotobuf(ws, "connect", {'uc_name': self.username}) 44 45 def sendprotobuf(self,ws,method,data): 46 msg = msgpb2.Msg() 47 msg.method = method 48 msg.data = json.dumps(data) 49 ws.send(msg.SerializeToString()) 50 logging.error("發送消息,類型:{},內容:{}".format(msg.method, msg.data)) 51 52 53 def startWebsocket(self): 54 # websocket.enableTrace(True) 55 logging.error("鏈接服務器:{},端口:{},用戶名:{}".format(self.host,self.port,self.username)) 56 ws = websocket.WebSocketApp("ws://{}:{}".format(self.host,self.port), 57 on_message=self.on_message, 58 on_error=self.on_error, 59 on_close=self.on_close) 60 ws.on_open = self.on_open 61 62 # ws.run_forever(ping_interval=5) 63 logging.error(datetime.datetime.now()) 64 ws.run_forever(ping_interval=5) 65 # ws.run_forever() 66 logging.error(datetime.datetime.now()) 67 68 69 #10.30.66.11 70 71 if __name__ == "__main__": 72 kwargs = {"host": "10.30.66.11", "port": 8886, "username": "liangyuanfang", } 73 p=ProtoService(**kwargs) 74 p.startWebsocket()
查詢運行過程當中,會把日誌寫到對應的文件中,經過統計文件內容分析測試結果app
這裏可能各位也注意到寫日誌,代碼使用了error級別,由於以前在調試時,info或者debug級別也會打印出一些引用組建的調試代碼,經過這種方式規避下socket