unless’s blog

日々のちょっとした技術的なことの羅列

Locust + AWS ECS(Fargate)で負荷試験環境を作った話

これはなに?

Kyash Advent Calendar 2020 21日目の記事です。

今回はKyashに導入した負荷試験環境について紹介します。

経緯

Kyashでは決済や入金周りの性能試験は実施していましたが、シナリオベースの負荷試験など不十分な部分がありました。
そのためキャンペーンなどで通常より多くのアクセスが発生した場合に、

  • どのくらい耐えれるのか
  • どこのサーバがボトルネック
  • 適切なスケール具合はどの程度か

などの情報で曖昧な部分がありました。

そこでシナリオベースな負荷試験を実施することにより、
事前にどの程度までスケールすればどの程度の負荷まで耐えられるのかを把握し
適切なタイミングでの適切なスケーリングを実現することで
システムを安定稼働をさせていきたいと考えました。

ツールの選定

負荷試験を実施するにあたり主な要件は下記でした。

  • loginしないといけないのでsession管理ができるもの
  • ある程度のシナリオを組めるもの
  • CloudServiceとのintegrationが容易なもの

色々なツールを比較し下記理由からLocustを使うことにしました。

  • 情報が多いのでいろいろ参考にできそう
  • ecsやfargateとの親和性も高そう
  • 分散実行がサポートされているためスケールも容易そう

locust.io

また、インフラ部分は基本的にAWSを使用しているのでAWS ECS(Fargate) でworkerを簡単にスケールできるようにしました。

構成

f:id:gettergot:20201203105802p:plain
kyash_locust

workerはFargateのtask数を変更することでスケール可能にしてます。
オートスケールにしなくても負荷が出ないなら手でtask数あげれば問題ないかなという判断です。
また、LocustのUIはOneLoginで認証(OIDC)を行ってます。
さらにDatadogでLocustの監視をしながらworkerの負荷状況もdashboardで確認できるようになっています。

Locustの構成

Locust側のDirectory構成は下記

$ tree -I '__pycache__' --prune locust/
locust/
├── common
│   ├── __init__.py
│   ├── auth.py
│   ├── const.py
│   └── env.py
├── locustfiles
│   └── 20203Q
│       └── locustfile.py
└── task_set
    ├── __init__.py
    ├── const.py
    └── wallet_tab.py

基本的には、どこをシミュレートして負荷を掛けるかによってファイルを別けています。

例としてtop画面に負荷を掛けるシナリオだと、SequentialTaskSetを使用してTop画面を表示するのにCallされるAPIを登録しています。 (コードはあくまで例なので実際は少し違います)

docs.locust.io

locustfile.py

from locust import HttpUser, constant
from task_set import wallet_tab

class KyashUser(HttpUser):
    tasks = {wallet_tab.WalletTabTaskSet: 1}
    wait_time = constant(0.01)

wallet_tab.py

from locust import SequentialTaskSet, task
from common import auth
from task_set.const import *


class WalletTabTaskSet(SequentialTaskSet):
    token = ""

    def on_start(self):
        auth_task = auth.AuthTask(self)
        self.token = auth_task.login(const.EMAIL, const.PASSWORD)

    @task
    def device(self):
        res = self.client.post("/v1/hoge", json={"device": {
            "token": const.DEVICE_TOKEN}}, headers={auth.AuthTask.getHeader(): self.token})
        print(res.text)

.....

LocustのUI

f:id:gettergot:20201208104632p:plain
locust_UI
負荷試験を開始するときは上記画面から値を設定します。

Number of users to simulateには、作成するクライアント数を指定します。 Hatch rateには、クライアント数の増加ペースを指定します。

どのくらい負荷を掛けているのかが簡易的ではありますが、ビジュアライズされていてわりと見やすい感じになってます。

f:id:gettergot:20201204101202p:plain
UI

まとめ

負荷試験を実施することで、課題であった、

  • どのくらい耐えれるのか
  • どこのサーバがボトルネック
  • 適切なスケール具合はどの程度か

を把握して戦略的にスケールすることが可能になりました。
また、いつの日かCI環境でリリースフローの中に組み込みたいという夢もあるので、引き続き負荷試験環境も整備していければと思ってます。

Kyash Advent Calendar 2020 の他の記事もぜひ読んでみてください。