イナゴによる負荷試験

負荷テストは、他のタイプのテストほど需要がなく、普及していません-そのようなテストを実行できるツールはそれほど多くありませんが、単純で便利なものは、一般的に片手で数えることができます。



パフォーマンステストに関しては、まず第一に、誰もがJMeterについて考えます。これは間違いなく、最も多くのプラグインを備えた最も有名なツールです。 JMeterは、Hello World以外のアプリケーションのテストが必要になるとすぐに、インターフェイスがわかりにくく、エントリのしきい値が高いため、JMeterが好きではありませんでした。



そして今、2つの異なるプロジェクトでのテストの成功に触発されて、私は比較的シンプルで便利なソフトウェア-Locustに関する情報を共有することにしました



あまりにも面倒くさい人のために、私はビデオを録画しました:







これは何ですか



分散負荷をサポートするPythonコードを使用して負荷シナリオを指定できるオープンソースツールで、著者によると、一連のBattlefildゲームのBattlelogの負荷テストに使用されました(すぐに魅力的)



プロから:





マイナスのうち:





テストプロセス



テストは複雑なタスクであり、計画、準備、実装の監視、結果の分析が必要です。 ストレステスト中に、可能であれば、結果に影響を与える可能性のあるすべてのデータを収集することが可能であり、必要です。





以下に説明する例は、ブラックボックス機能負荷テストとして分類できます。 テスト対象のアプリケーションについて何も知らなくても、ログにアクセスしなくても、パフォーマンスを測定できます。



始める前に



実際に負荷テストをテストするために、ローカルでシンプルなWebサーバーhttps://github.com/typicode/json-serverをデプロイしました。 次の例のほとんどすべてを彼に提供します。 デプロイされたオンラインの例( https://jsonplaceholder.typicode.com/)からサーバーのデータを取得しました

実行するには、nodeJSが必要です。



明らかなネタバレ :セキュリティテストと同様-禁止されないように、オンラインサービスをロードせずに、ローカルで猫のストレステストを行うことをお勧めします



開始するにはPythonも必要です。すべての例で、バージョン3.6とイナゴ自体(執筆時点ではバージョン0.9.0)を使用します。 コマンドでインストールできます



python -m pip install locustio
      
      





インストールの詳細は、公式ドキュメントに記載されています。



例の解析



次に、テストファイルが必要です。 それは非常にシンプルでわかりやすいので、ドキュメントから例を取り上げました。



 from locust import HttpLocust, TaskSet def login(l): l.client.post("/login", {"username":"ellen_key", "password":"education"}) def logout(l): l.client.post("/logout", {"username":"ellen_key", "password":"education"}) def index(l): l.client.get("/") def profile(l): l.client.get("/profile") class UserBehavior(TaskSet): tasks = {index: 2, profile: 1} def on_start(self): login(self) def on_stop(self): logout(self) class WebsiteUser(HttpLocust): task_set = UserBehavior min_wait = 5000 max_wait = 9000
      
      





それだけです! これでテストを開始できます。 始める前に例を見てみましょう。



インポートをスキップすると、最初の段階で、1行で構成される2つのほぼ同一のログインおよびログアウト機能が表示されます。 l.client-ロードを作成するHTTPセッションオブジェクト。 リクエストライブラリのメソッドとほぼ同じPOSTメソッドを使用します。 ほとんど-この例では、特定のサービスである完全なURLではなく、その一部のみを最初の引数として渡しているためです。



2番目の引数はデータを渡します-そして、自動的にjsonに変換されるPython辞書を使用するのが非常に便利であることに気づかずにはいられません



また、リクエストの結果は一切処理しません。成功した場合、結果(Cookieなど)はこのセッションで保存されます。 エラーが発生すると、記録されて負荷統計に追加されます。



リクエストを正しく記述したかどうかを知りたい場合は、次のようにいつでも確認できます。



 import requests as r response=r.post(base_url+"/login",{"username":"ellen_key","password":"education"}) print(response.status_code)
      
      





base_url変数のみを追加しました。 この変数には、テスト対象のリソースの完全なアドレスが含まれている必要があります。



次のいくつかの関数は、負荷を作成するクエリです。 繰り返しますが、サーバーの応答を処理する必要はありません。結果はすぐに統計に反映されます。



次はUserBehaviorクラスです(クラスの名前は任意です)。 名前が示すように、テスト対象のアプリケーションの真空下での球状ユーザーの動作を説明します。 ユーザーが呼び出すメソッドと呼び出しの頻度の辞書をタスクプロパティに渡します。 現在、各ユーザーがどの関数とどの順序で呼び出すかがわからないという事実にもかかわらず、ユーザーはランダムに選択されますが、 インデックス関数はプロファイル関数よりも平均2倍頻繁に呼び出されることを保証します。



動作に加えて、親クラスTaskSetでは、テストの前後に実行できる4つの機能を指定できます。 呼び出しの順序は次のとおりです。



  1. setup - UserBehavior(TaskSet)の開始時に1回呼び出されます -例にはありません
  2. on_start-起動時にロードの新しいユーザーごとに1回呼び出されます
  3. タスク -タスク自体の実行
  4. on_stop-テストの動作が終了したときに各ユーザーによって1回呼び出されます
  5. teardown - TaskSetの終了時に1回呼び出されます-例にもありません


ここで、ユーザーの行動を宣言する方法は2つあることに言及する価値があります。最初の方法は、上記の例ですでに示されています。 2番目の方法は、 UserBehaviorクラス内でメソッドを直接宣言することです。



 from locust import HttpLocust, TaskSet, task class UserBehavior(TaskSet): def on_start(self): self.client.post("/login", {"username":"ellen_key", "password":"education"}) def on_stop(self): self.client.post("/logout", {"username":"ellen_key", "password":"education"}) @task(2) def index(self): self.client.get("/") @task(1) def profile(self): self.client.get("/profile") class WebsiteUser(HttpLocust): task_set = UserBehavior min_wait = 5000 max_wait = 9000
      
      





この例では、ユーザー関数と呼び出しの頻度は、 タスクアノテーションを使用して設定されます 。 機能的には、何も変わっていません。



この例の最後のクラスはWebsiteUserです (クラスの名前は任意です)。 このクラスでは、ユーザー動作モデルUserBehavior *** +、および各ユーザーによる個々のタスクの呼び出し間の最小および最大待機時間を定義します。 より明確にするために、ここで視覚化する方法を示します。







はじめに



パフォーマンスをテストするサーバーを実行します。



 json-server --watch sample_server/db.json
      
      





また、サンプルファイルを変更して、サービスをテストし、ログインとログアウトを削除し、ユーザーの動作を設定できるようにします。



  1. 作業開始時にメインページを1回開く
  2. すべてのx2投稿のリストを取得する
  3. 最初の投稿x1にコメントを書く


 from locust import HttpLocust, TaskSet, task class UserBehavior(TaskSet): def on_start(self): self.client.get("/") @task(2) def posts(self): self.client.get("/posts") @task(1) def comment(self): data = { "postId": 1, "name": "my comment", "email": "test@user.habr", "body": "Author is cool. Some text. Hello world!" } self.client.post("/comments", data) class WebsiteUser(HttpLocust): task_set = UserBehavior min_wait = 1000 max_wait = 2000
      
      





コマンドプロンプトで開始するには、コマンドを実行します



 locust -f my_locust_file.py --host=http://localhost:3000
      
      





hostはテスト対象のリソースのアドレスです。 テストで示されたサービスのアドレスが追加されるのは彼にとってです。



テストにエラーがない場合、ロードサーバーが起動し、 http:// localhost:8089 /で利用可能になります。







ご覧のとおり、テスト対象のサーバーがここに示されています-テストファイルのサービスのアドレスが追加されるのはこのURLです。



また、ここでは、負荷に対するユーザー数と1秒あたりの成長を示すことができます。

ボタンで、ロードを開始します!







結果



一定時間後、テストを停止し、最初の結果を確認します。



  1. 予想どおり、開始時に作成された10人のユーザーはそれぞれメインページに移動しました
  2. 投稿のリストは平均して、コメントが書かれたよりも2倍頻繁に開かれました
  3. 各操作には平均および中央値の応答時間があります。1秒あたりの操作数は、今ではそれを取得して要件から予想される結果と比較しても、すでに有用なデータです


2番目のタブでは、負荷グラフをリアルタイムで見ることができます。 特定の負荷でサーバーがクラッシュしたり、その動作が変化した場合、これはすぐにグラフに表示されます。







3番目のタブで、エラーを確認できます-私の場合、これはクライアントエラーです。 ただし、サーバーが4XXまたは5XXエラーを返した場合、そのテキストはここに書き込まれます

テキストのコードでエラーが発生した場合、[例外]タブに分類されます。 これまでのところ、コードでprint()コマンドを使用することに関連する最も一般的なエラーがあります-これはログを記録する最良の方法ではありません:)



最後のタブでは、すべてのテスト結果をCSV形式でダウンロードできます



これらの結果は関連していますか? それを理解しましょう。 ほとんどの場合、パフォーマンス要件(記載されている場合)は次のように聞こえます。平均ページ読み込み時間(サーバー応答)は、Mユーザーの負荷でN秒未満でなければなりません。 ユーザーがすべきことを実際に指定していない。 そして、私はこれのためにイナゴが好きです-それはユーザーから期待される期待されるアクションをランダムに実行する特定の数のユーザーのアクティビティを作成します。



ベンチマークを実行する必要がある場合-異なる負荷でのシステムの動作を測定するために、動作のいくつかのクラスを作成し、異なる負荷でいくつかのテストを実行できます。



開始するにはこれで十分です。 この記事が気に入ったら、次の記事を書く予定です。






All Articles