LoginSignup
4
0

More than 1 year has passed since last update.

Rakuma に負荷試験がやってくる!?

Last updated at Posted at 2022-12-24

huka

前置き

本番相当な環境での負荷試験をプロジェクトで実施しようとしているので、こんな感じのものが将来的にはできるようになりそうという話を書いてみようかと思います。

今回の想定はこのような形を考えて話を進めていきます。

f0196084-658a-f768-309b-365940ff37c5.png

では見ていきましょう。

どんな負荷試験ができるようになると嬉しいか

できるだけ「本番環境そっくりの環境」で負荷試験をしたいと通常は思いますが、それは具体的にはどのような環境なのかを考えてみます。

  • 本番相当のスペック(APPサーバーやDBサーバーなど)
  • 本番相当のデータ量
  • 本番相当のリクエスト量

ぱっと思いつくものはこんなところでしょうか。

もう一つの条件:本番環境に影響を与えない

そして、前提条件として、

  • 本番環境に影響を与えない

というのが挙げられるかと思います。何を当たり前のことを言っているのかという感じかもしれませんが、意外とここが盲点というか重要だったりします。

本番データを利用した処理に注意する

例えばあるページにアクセスした際に、裏ではユーザーに何かしらの通知をする機能が実装されてるとします。本番のデータをそのまま利用して負荷試験を行った場合に、本物のユーザーに大量の通知を送ってしまうという障害につながる可能性があります。

  • 本番データをそのまま利用しない(データのマスキングをする)
  • 通知などの仕組みが確実に動かないような仕組みを入れておく

などの考慮が必要になります。

外部接続に注意する

例えば、自分たちの環境はそっくり本番相当の環境を別で作ったとしても、裏の GSP とかが同じものを使っているとしたらどうでしょうか。

  • GSP に本番以外のデータを登録してしまう
  • GSP に負荷をかけてしまうことによって、本番での障害につながる

などの可能性が考えられます。

仮に、STG 用の GSP を叩いたとしても、

  • STG の GSP では負荷に耐えられない
  • 他の STG 環境に影響をあたえてしまう

といった可能性が考えられます。

なので、負荷試験を行う上で考慮したいもう一つのポイントとして、外部接続先については

  • Mock を用意して、本物の接続先を叩かない
  • 負荷試験環境を外部接続先でも用意してもらう(通常これは難しかったりする)

のいずれかが必要になってきます。

また、可能であれば、Mock や負荷試験用の外部接続先以外は接続できないようになっていると、事故を防ぐという意味ではとても安心です。

(改めて)どんな負荷試験ができるようになると嬉しいか

computer_server_chara2_smile

今までの話をまとめると、負荷試験環境の要件は以下になりました。

  • 本番相当のスペック(APPサーバーやDBサーバーなど)
  • 本番相当のデータ量
  • 本番相当のリクエスト量
  • データはマスキングしておく
  • 外部接続は Mock を利用する
  • Mock 以外の外部接続は遮断しておく

ここからは1つ1つの要件を満たすための仕組みなどを詳しく見ていこうと思います。

- 本番相当のスペック

これは、まあ用意すればいいだけの話なので技術的に難しい話というわけではないです。

本番相当のスペックにしておきたいものとしては、

  • EKS のNode
  • RDS (Aurora)
  • ElastiCache (Memcached, Redis)

あたりでしょうか。

- 本番相当のデータ量&データのマスキング

本番DBをコピーしてマスク処理をかけることを考えました。

ちなみに弊社では、本番のネットワーク以外に本番 DB のコピーを作成する際はデータのマスク処理が必須になります。ですので、クエリの性能検証や Index 追加の検証用に行っていた本番 DB コピー運用も、今後はマスク処理をかけていこうという話を SRE 内部でしています。

- どの項目をマスクするの?

会社としては、機密情報をマスクしなさいという大方針は示されているものの、じゃあ具体的にどのテーブルのどのカラムをマスクしたらいいのか? についてはアプリ側で1つ1つ丁寧に見ていくしかありません。

この辺は公開できないため具体的なことは書けませんが、多くの方と議論を重ね、各テーブルの各カラム1つ1つについてマスクしておいたほうが良さそうかということを決めていきました。

当然の疑問として、今後追加になるカラムについてはどうするのか? という話が出てくるわけですが、この辺はまた別のチーム考えていく想定です。(一旦、今あるものを精査することに意味があると思っているので)

- マスク処理はどうやってるの?

もともと実装されていた Ruby スクリプトを切り出して、並列処理をできるような仕組みを導入しました。

切り出した理由として

  • DB の接続情報が rails と同じものが利用されている
    • 誤って利用中の DB にマスク処理を実行してしまうリスクがある
    • 一時的な DB に対して実行したい場合は、別途接続情報を変更する必要がある
  • マスク処理では利用しないコンフィグ系の YAML ファイルなども、マスク処理実行用環境で必要になる
    • マスク処理は並列実行したいため、メインアプリとは別の k8s マニフェストで管理することになる
      • 二重管理となる

これらのリスクの回避や、二重管理のコストを抑えるために、マスク処理の分離を検討しました。

ちなみに ArgoWorkflow を使った並列処理の話は別の記事で言及しています

この結果、約6時間でマスク処理を完了できるようになってます。

- 本番相当のリクエスト量

可能な限り「本番と同じリクエストを投げたい」となるわけです。

対象のエンドポイントが増えれば増えるほど、このあと出てくる Mock データの作成の難易度が上がってきたり、更新系のエンドポイントの場合はさらにデータの状態についても考慮が必要になってきます。

そこで、まずは本番で負荷をかけている(=リクエスト量の多い)エンドポイントを調べることにしました。

本番のリクエスト量を調べる

にあるように、Redash 経由で BigQuery のアクセスログから、リクエストの多いエンドポイントを調べました。

そして、全体のリクエスト数の90%をカバーできるような負荷試験対象のエンドポイントを絞り込みました。

リクエスト時のパラメータを集める

対象のエンドポイントが決まっても、同じクエリパラメータでリクエストを投げ続けていては、内部で持つキャッシュなどが効きすぎてしまい、精度の高い負荷試験にならない可能性があります。

可能であれば本番で流れた同じリクエストを流しながら負荷試験を行いたい。そこで、各種ログから各エンドポイントへのリクエストパラメータを集めることにしました。

こちらは CloudLogging 上にある Rails のログをいろいろゴニョゴニョすることで、必要な情報を集めることができました。

認証用のパラメータは?

認証していないと叩けないエンドポイント、あるいは認証情報に応じて処理内容が変わるエンドポイントもありそうです。

認証周りの仕組みは、API も WEB も トークン情報(ユーザー毎に固定の値)をヘッダーに付与することで、認証をパスすることができます。しかし、そのトークン情報はログには記録されていません(セキュリティ上その方がいい)。

代わりに UserID を利用する方式を考えました。具体的には、

  • アクセスログから UserID を取得
  • ユーザーの一覧テーブルからトークンカラムの値を UserID で上書き
    • これで UserID をトークンとして送信することで認証させることができる

API については Rails のログの中に UserID が含まれていましたが、Web は Rails のログには含まれておらず、この方式は API のみに採用できそうです。

Web については BigQuery のアクセスログに UserID があったので、調べたところ一定数のリクエストが認証情報ありのリクエストになってました。少なくない割合ではありますが、Web のアクセスの大半は認証なしでもアクセスできる参照系のエンドポイントだったので、Web については認証を諦めることにしています。

本番相当のリクエストを投げる負荷試験ツール

対象のエンドポイントやパラメータは集められました。

続いては、この情報を元に本番相当のリクエスト数を発生させる仕組みについて考える必要があります。まずは、1日平均の RPS (request per seconds) を算出します。そしてこの量のリクエスト数を、負荷試験ツール側も並列実行してあげる必要があります。

いろいろ世の中的に使われているツールを調べたり検証したりしながら、最終的に Gatling を並列実行させる方式にしました。対象のエンドポイント毎にシナリオ/パラメータファイルを作成し、シナリオ毎に並列実行をさせる感じ。です。

- 外部接続はMockを利用する

spec などの UnitTest 系で利用される Mock と違って、こういった場合に利用したい場合の Mock とは

  • HTTP の Request を受け付けることができる
  • 予め設定して内容に応じて、リクエストの内容を元に、固定または動的なレスポンスを返却する

ような API になります。

このようなことができる Mock ツールはいろいろありますが、Mock を利用するには通常かなりの手間がかかるので、その辺で楽ができるものを採用したいと考えました。

そういう観点で Mock ツールに対する要件を追加すると、

  • プロキシとして利用することができる
    • アプリの接続先を Mock に1つ1つ切り替えることもできるが面倒。プロキシを利用する設定を1つ追加する方が簡単。
  • Mock データの作成を簡略化できる
    • 接続先毎に1から手作りで Request、Response を定義していく手間を簡略化できると嬉しい

といったところでしょうか。

その辺を加味しながらというか以前使ったことあった WireMock というツールで賄えそうだったので、今回は WireMock を使うことにしています。

それぞれの要件をどうクリアしているか見ていきたいと思います。

プロキシとして利用することができる

curlで表現すると、

curl http://abc-api.com/

ではなく、

curl --proxy http://my-wiremock:8080 http://abc-api.com/

こんな感じのリクエストをアプリケーションからしてもらうようにするイメージです。

Ruby の場合、HTTP_PROXYHTTPS_PROXY の環境変数をセットしておくことで、簡単に Faraday などで作成される HTTP リクエストをプロキシ経由にすることができる。

WireMock はプロキシモードをサポートしているので、WireMock のドメインとポートをプロキシとして設定してあげることで、簡単にいろいろな接続先に対しての Mock として機能させることができます。

Mockデータの作成を簡略化できる

WireMock は、Request のパターンを Json で記述し、Response をファイルに記述しておくことで簡単に設定することができます。以下をご覧ください。

さらに嬉しいのが、Record モードです。

Record モードで起動させ、WireMock をプロキシとして外部に接続することで、実際のアプリからのリクエストと外部接続先からのレスポンスを Mock 用の Json ファイルとして保存することができます。

これで生成された Mock ファイルを元に WireMock を通常モードで起動させることで、負荷試験の際には Mock データを返すことができるようになります。

ただ、実際には作成された Mock の Json ファイルやレスポンスの一部を以下のような理由で書き換える必要があったりします。

  • いろんなパラメータを受け付けられるように URL を固定ではなく、正規表現に直す
  • レスポンスがそのままでは不都合がある場合は修正する
    • 例:STG のデータが返ってきてるけど、本番 DB のコピーを使うので、本番用の ID に書き換えたり

ただ、素で1から作るよりは簡単にはなるはずです。

- Mock以外の外部接続は遮断しておく

万が一にも、本番のデータを使って外部処理を叩いてしまい、想定していない事(特に何かしらの通知がユーザーに飛んでしまうなど)が起きないようにしておきたいです。

また、負荷試験実施中には外部接続先をたくさん叩いてしまって意図せず落としてしまうような自体も避けたいです。

そこで、許可していない外部の接続先以外には接続ができないようにしておきたくなるのですが、コンテナ環境で導入している Istio とよばれる ServiceMesh の機能を利用するとこれが実現できます。

ServiceEntry と呼ばれるリソースに予め接続してもよい接続先を記載しておき、 Mock データを作成します。実際に負荷試験ツールでシナリオを実行する際には、この設定を削除しておき、どこの外部接続にも接続できないようにしておきます。

まとめ

gekijou_end_owari.png

ここまで見てもらったように、いろいろな工夫、仕組みを導入することで、負荷試験に求められる要件を満たせそうなことが分かりました。いまは、これを元に負荷試験の計画や手順をまとめ、実際に負荷試験を実施を試みています。

まだまだやり始めたばかりで課題も多く、すぐに誰でもいつでも使える状態にすることは難しいですが、そう遠くない未来に、好きなタイミングに負荷試験が実施できるようになるといいなぁと思ってます。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0