ウェブサイトのロードテストにPythonを使用する方法

新しいWebアプリケーションを持っていると想像してください。少数のユーザーでパフォーマンスが良いことを知っていますが、期待される負荷を超える増加したトラフィックに対して、アプリケーションはどのように応答するでしょうか?Pythonを使用してWebアプリケーションに負荷テストを実行してください!

この記事では、一度に複数のユーザーがアプリケーションにアクセスすることをシミュレートしてWebアプリケーションに負荷テストを実行する方法を学びます。

ウェブサイトの負荷テストを開始するには、続けてください。

前提条件

このチュートリアルは実践的なデモンストレーションになります。一緒に進める場合は、次のものを持っていることを確認してください:

静的ウェブサイトのセットアップ

Before running a load test against a website, you first must set up a demo site. You’ll create a static website and a demo API for this tutorial, but here you will focus on the static website first. A static website will show you the load testing basics, while an API will show you how to pass different parameters simulate different operations。

もしAPIに対しての負荷テストを開始したい場合は、Locustをインストールし、マシン上で実行する次のセクションに進んでください。このチュートリアルのデモでは、Swagger PetstoreデモAPIが使用されます。

  1. お好きなコードエディタで新しいファイルを作成し、以下のコードを新しいファイルにコピーして、お好きな名前で保存します。この例では、ファイルの名前はload_test_page.htmlです。

以下はHTMLドキュメントで、Webブラウザで開くと「これはテストページです。」と表示されます。

<!DOCTYPE html>
<html>
	<head>
		<title>ATA Load Balancing Demo</title>
	</head>
	<body>
		<h1>This is a test page.</h1>
	</body>
</html>

2. 次に、お気に入りのWebブラウザを開き、Azure Portalのストレージアカウントに移動します。

3. ストレージアカウント内で静的ウェブサイトホスティングを有効にし、ウェブサイトのホームページを設定するために以下の手順に従ってください:

  • 左側のナビゲーションパネルで静的ウェブサイトをクリックします。静的ウェブサイトページでは、デモサイトのファイルをアップロードします。
  • 以下に示すように、有効をクリックして静的ウェブサイトホスティングを有効にします。
  • インデックスドキュメント名フィールドにload_test_page.htmlを入力し、保存をクリックします。これにより、Blobコンテナとウェブサイトを指すURL(プライマリエンドポイント)が自動的に作成されます。URLはまだ機能しませんが、後で使用するために保存しておきます。
Enabling Static Website Hosting

4. 左のパネルでストレージエクスプローラー(プレビュー)をクリックし、ブロブコンテナ→$webに移動します。静的ウェブサイト機能によって作成された$webブロブコンテナは、すべての静的ファイルをホストします。

アップロードをクリックし、ステップ1で作成したload_test_page.htmlをアップロードします。

Uploading Static Files (HTML Page)

5. 最後に、ウェブブラウザの新しいタブを開き、ステップ2でメモしたURLに移動し、URLが正常に動作するか確認します。

Accessing Static Website’s URL

Locustフレームワークのインストール

テストするサイトができましたが、まだウェブサイトをテストするための負荷テストツールが必要です。高負荷テストを管理するためのコードを書くのは時間がかかり、エラーが発生する可能性があります。なぜLocustフレームワークを使用しないのでしょうか?LocustはPythonで書かれたオープンソースのツールで、pipパッケージマネージャを使用してインストールできます。

Pythonを復習する必要がある場合は、初心者向けのPython関数をチェックしてください。

Locustは、静的サイト、Webアプリケーション、またはAPIに対して負荷テストを実行できます。テスト対象がHTTP(S)エンドポイントを持っている必要がある唯一の要件です。

デフォルトでは、pipパッケージマネージャーは、LinuxおよびMacOSの~/.localディレクトリにパッケージをインストールしますが、これはシステムパスにありません。このパスはPython仮想環境でのみ利用可能です。したがって、このチュートリアルではpipを使用します。

  1. ターミナルを開いて、以下のコマンドを実行して新しい仮想環境を作成し、Locustをインストールします。
# venvモジュールを使用して新しいPython仮想環境を作成します
python3 -m venv venv 
# 仮想環境をアクティブにします
source venv/bin/activate 
# 新しい仮想環境にLocustをインストールします
python3 -m pip install locust
Starting and installing locust in a virtual environment

2. 新しいディレクトリを作成し、そのディレクトリに移動するために以下のコマンドを実行します。これにより、Locustファイルがコードベースの残りから分離され、整理が容易になります。この例では、ディレクトリの名前はlocust_dirです。

mkdir locust_dir
cd locust_dir

3. 最後に、locust_dirディレクトリにlocustfile.pyという新しいファイルを作成し、次に、locustfile.pyファイルに以下のコードをコピー/貼り付けします。このファイルには、ユーザーのシミュレーション方法、それらのユーザーがアクセスするエンドポイント、および渡すパラメータなどのテスト命令が含まれます。

Locustが実行されると、locustfile.pyという特定のファイルを探します。したがって、そのファイルを別のディレクトリ(locust_dir)に保存し、Locustがそれを見つけることができるようにするのが最適です。これにより、他のテストを上書きせずに追加のテストを作成できます。

以下のコードは、提供されたホスト名のパスに対してHTTP GETリクエストを実行します。これは、コマンドラインからcurl http://<Host>/を実行するのと同等です。

レスポンスを受信すると、Locustは直ちに次のリクエストを送信し、このプロセス全体がテスト内のすべての仮想ユーザーに対して繰り返されます。

# Locustからクラスをインポート
from locust import HttpUser, task 

# 新しい仮想ユーザーをインスタンス化
class HelloWorldUser(HttpUser): 
    # 以下のメソッドをLocustが扱うように指示します
    # それを仮想ユーザーが行うものとして
    @task 
    # 新しいメソッドを定義
    def hello_world(self): 
        # このメソッドはパス`/`に対してHTTP GETリクエストを実行します
        # テストしているサイトの
        self.client.get("/") 

パスが不完全に見える場合、それはそのようなものです。locustファイルではパスとクエリパラメータのみが定義されており、ホストは実行時に渡されます。このメソッドは次のステップでより意味をなします。

静的サイトに対する負荷テストを実行します

Locustをインストールしたら、負荷テストを実行する準備が整いました!負荷テストは、アプリケーションの動作を見るために一連のWebリクエストを記述する以上のものです。完全なテストは、さまざまなエンドポイントと構成での応答時間、失敗率、およびエラーコードを記録します。

Locustは、コマンドラインまたはWebインターフェースから呼び出すことができる柔軟性があります。このチュートリアルでは、Webインターフェースを使用して静的サイトに対する負荷テストを実行します。

locustコマンドを実行して、locustfile.pyファイルからテストシナリオを使用してlocustグラフィカルアプリケーションを起動します。

locust 
Run the locust command

2. Webブラウザを開いて、http://localhost:8089/ に移動してLocustにアクセスします。 8089ポートは、Locustが実行されるデフォルトのポートです。

「静的ウェブサイトの設定」セクションのステップ3でメモしたURL(プライマリエンドポイント)を覚えていますか?次のステップで使用するのは今です!

3. 最後に、スクリーンショットの中で見られるように、URL(プライマリエンドポイント)をホストフィールドに入力し、スワーミングを開始をクリックして負荷テストを開始します。これにより、locustfile.pyでのテストが、Hostフィールドに入力したURLに対して実行されることが示されます。

このデモでは、ユーザー数またはスポーン率フィールドの値を変更することは任意です。

同時に作成される仮想ユーザーのは、最大の仮想ユーザー数です。同時に、スポーン率は、Locustが仮想ユーザーの最大同時数に達するまで、毎秒作成されるユーザーの数です。テストを停止するまで、仮想ユーザーの数は最大のままです。

Running Locust load test on localhost:8089

テストを実行すると、Locustはホストを追加し、ユーザークラス内の各パスに対してリアルタイムでリクエストを送信します。応答が受信されると、Locustはすぐに別のリクエストを送信します。

以下に、テストされたエンドポイントのリストと応答時間、失敗、および秒ごとのリクエストに関する統計情報が表示されます。

Viewing Locust Chart Showing the Number of Requests, Failures, and Response Times for the Test Case

ウェブサイトのパフォーマンスメトリクスをグラフィカルに表示する場合は、以下に示すようにチャートタブをクリックしてください。

Viewing graphical output of load tests statistics

APIに対する負荷テストの実行

Locustの基本に慣れたので、より現実的なテストケースを見てみましょう。静的なサイトはかなり安定しており、パフォーマンステストを実行する際にはあまり問題が発生しません。ではなぜAPIに対して負荷テストを実行するのでしょうか?

APIは応答の変動が多く、安定していないホスティングオプションがあり、ダウンタイムが発生した場合、組織にとってはより多くの潜在的な影響があります。

APIやその動作に不慣れであれば、記事があり、認証、HTTPメソッド、およびJSON応答などの基本事項が説明されています。記事はPowerShell向けですが、APIの概念はこの記事の後半で重要になります。

  1. locustfile.pyファイルの内容を以下のコードで置き換えてください。これはいくつかのことを行います:
  • Locustが新しい仮想ユーザーをインスタンス化するときに、ユーザーを認証するためのGETリクエストを実行します
  • ホスト上でGETリクエストを実行しますが、そのリソースが存在しないため失敗します
  • JSONボディを通過させるPOSTリクエストを同じエンドポイントの範囲内で実行します。
import time # Pythonシステムライブラリからtimeをインポートする
from locust import HttpUser, task

class HelloWorldUser(HttpUser):

    # ユーザーがインスタンス化されたときにこのタスクが実行されます
		def on_start(self): 
        # ペットストアAPIにはユーザーデータベースがないため、
        # 任意のユーザー名とパスワードが機能します
        username = "foo" 
        password = "bar"
        # これはAPIドキュメントのloginUserエンドポイントに準拠する必要があります
        self.client.get("/user/login?username="+username+"&password="+password) 

    # このタスクはhttps://petstore.swagger.io/v2/にエンドポイントがないため失敗します
    @task
    def hello_world(self): 
        self.client.get("/")

    # タスクデコレータの後の(3)は、Locustにこのタスクを3倍の頻度で実行するように指示します
    @task(3) 
    def update_pets(self):
        # forループを使用して、0〜4まで数え、以下のHTTPリクエストで使用します
        for pet_id in range(5): 
            # HTTP POSTリクエストを実行してJSONボディを渡す
            self.client.post(f"/pet?petId={pet_id}", json={"name":"Mittens"}) 
            time.sleep(1) # 続行する前に1秒待機します

テストクラスにon_startステートメントを追加しないと、他のメソッドをテストしようとしたときに「403 Not Authorized」エラーが返されます。このメソッドをコメントアウトしてLocustを再実行して、テストにどのように影響するかを確認してください。

2. 次に、ペットストアAPIのドキュメントを開きます。上記のテストケースは、このAPIのために特に書かれているので、このチュートリアルと一緒にこのページを開いて、エンドポイントを確認するのに役立ちます。

以下のlocustコマンドを、「静的サイトへの負荷テストの実行」というセクションで行ったのと同じように実行してください(ステップ1)。

locust
Run the locust command

最後に、Locust UIでホストとしてhttps://petstore.swagger.io/v2を入力してください。

Viewing endpoints of pet store API being tested

結論

このチュートリアルでは、静的ウェブサイトとAPIに対する負荷テストの実行方法を学びました。これで、ユーザーの大量の殺到に対してサイトをテストする方法がより理解できるようになりました。リリース前のアプリケーションの準備に負荷テストは役立ちます。同様に、自動スケーリングの設定や低遅延のアプリケーションパフォーマンスのテストにも役立ちます。

今、現在のアプリケーションやサポートしているアプリケーションについて考えてみてください。同時に使用される大群のユーザーがそれを使用した場合、どのように反応するでしょうか?負荷テストシナリオが、アプリケーションのパフォーマンスを向上させるために何を指摘できると思いますか?

Source:
https://adamtheautomator.com/load-test/