[Python同時リクエスト(パート1)](http://mp.weixin.qq.com/s?__biz=MzAwMzY3MTU3Nw==&mid=2650527260&idx=1&sn=b2cbbbb3d155b5b57beda28e2a35d0c1&chksm=8338e56ab44f6c7c8039d01af85e5f5f87998b1cd7671d9fe090dbf2bf6a1e8850f7630ec5c9&scene=21#wechat_redirect)では、マルチスレッドメソッドを使用して、同時リクエストが多いサーバープログラムをテストするためのパフォーマンステストツールを作成する方法について詳しく説明しています。このテストツールでは、同時リクエストが多いと、非常に包括的な応答時間、スループット、エラー率、およびその他の関連情報が得られます。
パフォーマンステストでは、CPUとIOを集中的に使用するものが多くなります。基本的に、サーバー側のプログラムの多くはIOを集中的に使用するため、マルチスレッドの使用効率が高くなります。以前のコードを変更しました。パフォーマンステストの結果情報データを簡単に取得できるようになったので、他の人が直接APIを呼び出せるように、Flask-Restfulと組み合わせたフレームワークに基づくAPIとして提供しますか?テスト対象のサーバーのプログラムをテストできます。これは、より効率的で簡単です。もちろん、これは単なるアイデアです。サーバー側のテストでは、高い同時実行性と継続的な要求を前提として、サービスがOOM、SockedTimeOut、TimeOut、およびMQなどの他のプログラム情報として表示されるかどうかをさらに検討する必要があります。メッセージのバックログ、サービスの故障、その他の異常な状況。この記事では、ここではサービスの監視について詳しく説明しません。saasization中のサービスの監視については、私の記事[Saasizationアーキテクチャでのサービス監視](http://mp.weixin.qq.com/s?__biz=MzAwMzY3MTU3Nw==&mid=2650526960&idx=1&sn=63a1717e5655e08d5b74e5bd77d36da1&chksm=8338e786b44f6e9084c30a7554f16071a2a4630f7181927b5a2696233b011be3267d718412e7&scene=21#wechat_redirect)の実装アイデアと特定のコードを参照してください。
以下に、特定のテスト済みAPIをカプセル化します。これは、Taobaoホームページをテストする場合です。目的は、PostManテストツールを使用することです。同時実行数とテストするアドレス(ここではTaobao)を入力するだけです。 [リクエストの送信]をクリックすると、応答時間などの他のパフォーマンステストデータを取得できます。具体的なソースコードは次のとおりです。
#! /usr/bin/env python
#! coding:utf-8from flask import Flask,make_response,jsonify,abort,request
from flask_restful import Api,Resource
from flask import Flask
import requests
import time
import matplotlib.pyplot as plt
from threading import Thread
import datetime
import numpy as np
import json
import re
import hashlib
from urllib import parse
import datetime
app=Flask(__name__)
api=Api(app=app)
def getHeaders(url=None,caller='ucenter-interface-service',secret='6A3012039B5746CEA350B119535C45E0'):'''
: param pathurl:リクエストアドレス
: param caller:ヘッダーフィールドの呼び出し元を要求する
: param secret:リクエストヘッダーフィールドシークレット
: return:リクエストアドレスが分割され、md5暗号化のためにスプライスされた後、それはリクエストヘッダーに属します
'''
result1 = re.compile(r'\/([^\/]*)\/(v\d+|\d\.\d)\/(.+)')
result2 = result1.search(url)
contextPath = result2[1]
version = result2[2]
requestPath = result2[3]if requestPath.endswith('/'):
requestPath = requestPath[:-1]
tempArray = requestPath.split("/")
requestPath =""
i =0for str in tempArray:
# print(i)if tempArray[i]!="":
# print(parse.quote(tempArray[i]))
# print(tempArray[i])
requestPath = requestPath +"/"+ parse.quote(tempArray[i])
i = i +1
nowTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
singStr= secret +"callerService"+ caller +"contextPath"+ contextPath +"requestPath"+ requestPath +"timestamp"+ nowTime +"v"+ version + secret
sign=hashlib.md5(singStr.encode(encoding='utf-8')).hexdigest().upper()
dict1={'X-Caller-Service':'ucenter-interface-service','X-Caller-Timestamp':nowTime,'appSecret':'kOsqkHX2QcB7KVzY03NmqbafIjSnCneG','Content-Type':'application/json','X-Caller-Sign':sign,}return dict1
classOlapThread(Thread):
def __init__(self,func,args=()):'''
: param func:テスト中の機能
: param args:テストされている関数の戻り値
'''
super(OlapThread,self).__init__()
self.func=func
self.args=args
def run(self)-> None:
self.result=self.func(*self.args)
def getResult(self):try:return self.result
except BaseException as e:return e.args[0]
def taoBao(code,seconds,text,requestUrl):'''
高同時性プロシークタオバオ
: param code::param seconds::param text::param requestUrl:リクエストアドレス
: return:'''
r=requests.get(url=requestUrl)print('昨日のステータスコードを出力:{0},回答結果:{1}'.format(r.status_code,r.text))
code=r.status_code
seconds=r.elapsed.total_seconds()
text=r.text
return code,seconds,text
def calculationTime(startTime,endTime):'''2回の差を計算します。単位は秒です。'''return(endTime-startTime).seconds
def getResult(seconds):'''サーバーの応答時間情報を取得します'''
data={'Max':sorted(seconds)[-1],'Min':sorted(seconds)[0],'Median':np.median(seconds),'99%Line':np.percentile(seconds,99),'95%Line':np.percentile(seconds,95),'90%Line':np.percentile(seconds,90)}return data
def show(i,j):'''
: param i:リクエストの総数
: param j:応答時間リストを要求する
: return:'''
fig,ax=plt.subplots()
ax.plot(list_count,seconds)
ax.set(xlabel='number of times', ylabel='Request time-consuming',
title='olap continuous request response time (seconds)')
ax.grid()
fig.savefig('olap.png')
plt.show()
def highConcurrent(count,requestUrl):'''
高い同時リクエストをサーバーに送信する
: param count:並行性
: param requestData:リクエストパラメータ
: param requestUrl:リクエストアドレス
: return:'''
startTime=datetime.datetime.now()
sum=0
list_count=list()
tasks=list()
results =list()
# 失敗したメッセージ
fails=[]
# 成功したタスクの数
success=[]
codes =list()
seconds =list()
texts=[]for i inrange(0,count):
t=OlapThread(taoBao,args=(i,i,i,requestUrl))
tasks.append(t)
t.start()print('テスト:{0}'.format(i))for t in tasks:
t.join()if t.getResult()[0]!=200:
fails.append(t.getResult())
results.append(t.getResult())for item in fails:print('失敗した情報の要求:\n',item[2])
endTime=datetime.datetime.now()for item in results:
codes.append(item[0])
seconds.append(item[1])
texts.append(item[2])for i inrange(len(codes)):
list_count.append(i)
# 視覚的なトレンドチャートを生成する
fig,ax=plt.subplots()
ax.plot(list_count,seconds)
ax.set(xlabel='number of times', ylabel='Request time-consuming',
title='taobao continuous request response time (seconds)')
ax.grid()
fig.savefig('taobao.png')
plt.show()for i in seconds:
sum+=i
rate=sum/len(list_count)
# print('\n合計期間:\n',endTime-startTime)
totalTime=calculationTime(startTime=startTime,endTime=endTime)if totalTime<1:
totalTime=1
# スループットの計算
try:
throughput=int(len(list_count)/totalTime)
except Exception as e:print(e.args[0])getResult(seconds=seconds)
errorRate=0iflen(fails)==0:
errorRate=0.00else:
errorRate=len(fails)/len(tasks)*100
throughput=str(throughput)+'/S'
timeData=getResult(seconds=seconds)
# print('合計時間:',(endTime-startTime))
timeConsuming=(endTime-startTime)return timeConsuming,throughput,rate,timeData,errorRate,len(list_count),len(fails)classIndex(Resource):
def get(self):return{'status':0,'msg':'ok','datas':[]}
def post(self):if not request.json:returnjsonify({'status':1001,'msg':'リクエストパラメータはJSONデータではありません。確認してください。ありがとうございます。'})else:try:
data={'count':request.json.get('count'),'requestUrl':request.json.get('requestUrl')}
timeConsuming,throughput,rate,timeData,errorRate,sum,fails=highConcurrent(
count=data['count'],
requestUrl=data['requestUrl'])print('総実行時間:',timeConsuming)returnjsonify({'status':0,'msg':'リクエストは成功しました','datas':[{'スループット':throughput,'平均応答時間':rate,'応答時間情報':timeData,'エラー率':errorRate,'リクエストの総数':sum,'失敗の数':fails
}]},200)
except Exception as e:return e.args[0]
api.add_resource(Index,'/v1/index')if __name__ =='__main__':
app.run(debug=True,port=5003,host='0.0.0.0')
# print(highConcurrent(count=5))
次の図に示すように、PostManを呼び出します。
[送信]をクリックすると、PostManに表示される結果情報は次のようになります。
各リクエストの応答時間の視覚化されたトレンドチャートは次のとおりです。
Recommended Posts