Pythonでの同時リクエスト(パート2)

[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

Pythonでの同時リクエスト(パート2)
Pythonでの同時リクエスト
pythonの関数
1分でPythonを学ぶ|オブジェクト指向(パート1)
03.Pythonエントリの演算子
Pythonの結合関数
12.Python3でのネットワークプログラミング
pythonでステートメントを印刷する
Ubuntuにpythonをインストールする
python tic-tac-toe-textバージョン(パート2)
Pythonでのコンテキスト管理
pythonの算術演算子
pythonでguiを書く
PythonでのMongoDBの使用
PythonのStr文字列
Pythonでの計算ジオメトリ
Pythonのタプルの添え字
Pythonでの継承について話す
Python3.9の注目すべき更新ポイント
Pythonアプリケーションを3分でコンテナ化
pythonのイントロスペクションとは何ですか
pythonのオブジェクト指向とは何ですか
Pythonのジェネレーターとイテレーター
Pythonで文字列について話す
pythonでのwheelの使用法
Pythonの対数法の要約
Python開発でのパンダの使用
pythonでnohupコマンド命令を使用する
pythonのリスト内包表記とは何ですか
pythonに関数のオーバーロードはありますか
PythonでNumpyを使い始める
詳細な並べ替えアルゴリズム(Pythonで実装)
pythonコードでラップする方法
Pythonでのrc1の意味
pythonの一般的なエラーと解決策
Python開発でのnumpyの使用
pythonのdefは何をしますか
Pythonで括弧を省略する方法
Pythonでの辞書の詳細な使用法
pythonでのosパッケージの使用
Pythonでのガベージコレクションについて学ぶ
pythonでクラスを書く方法
pythonで数値をフィルタリングする方法
Pythonの数字は何ですか?
PythonでExcelを読む方法
Pythonにはいくつかのキーワードがあります
Pythonのすべてがオブジェクトです
pythonでエラーを表示する方法
npはpythonで何をしますか
pythonでreturnを書く方法
Pythonのモジュールについて話す
Pythonで変数を理解する方法
pythonで変数をクリアする方法
pythonでのタプルの使用法
Pythonリクエストモジュールセッションコード例
PythonでSQLiteを使用する方法
PythonはモジュールのCookieインスタンス分析を要求します
pythonmysqlのパラメータ化の説明