BASEプロダクトチームブログ

ネットショップ作成サービス「BASE ( https://thebase.in )」、ショッピングアプリ「BASE ( https://thebase.in/sp )」のプロダクトチームによるブログです。

外部APIコールを含むプログラムの負荷試験

f:id:ymiyamura:20190122163945j:plain

サーバサイドエンジニアの宮村です。

カートの負荷試験について、第3弾の記事です。 最初の記事 でも触れましたが、今回の負荷試験実施にあたり、外部サービスを模擬するモックサービスを作成しました。

外部サービスへ接続する負荷試験を行うには

今回、負荷試験の対象としたのは、BASEのカートシステムです。

カートシステムには決済時に外部サービスを利用する箇所があり、通常の開発時には、外部サービスより提供されている検証環境へ接続しています。

一般的に提供されている検証環境は、本番環境ほどの性能ではなかったり、他の利用者と共用しているというものではないでしょうか。そのため、利用者の都合で自由に高負荷をかけることは難しいと言えます。 負荷試験のような高負荷をかけることが可能か否か、また可能な場合、自由に実施してよいか、事前申請が必要かなどを確認し、それなりの準備を行う必要があります。

また利用が可能だったとして、外部サービス要因でパフォーマンス影響が出る懸念、送信するリクエストの制約など、外部サービスの提供する環境を使用する場合に考慮しなければならない点がいくつかあることがわかってきました。

f:id:ymiyamura:20190225153132p:plain

外部サービスへ接続しない

一方で、提供されている検証環境を使用せずに負荷試験を実施することについて検討します。

  1. 提供されている検証環境と同等の動作をするモックサービスを用意し、接続先を変更する
  2. 提供されている検証環境へ接続する処理を、外部接続せずに処理が完了するように変更する
  3. いっそのことすべてを本番環境で行う

本番環境との差異を小さくするという点において、3を除けば、プログラムの変更が少なくなる1の方法が有利と言えそうです。 稼働中のサービスで3を行うのは、リスクが高い上に、検証等の準備を含めるとコストが低いとは言えません。

調査を行ったところ、用意するモックサービスは、

  • BASEのサービスからのリクエストに対して
  • 処理可能な形式のレスポンスを
  • 適切な時間をかけて返してくれれば十分

という見通しを持つことができました。

これであればモックサービスを準備することが有力な選択肢になるだろうということになり、検討を始めました。

f:id:ymiyamura:20190225153217p:plain

モックサービスとしてSwaggerを検討する

さて、モックサービスをどのように準備するかということになり、調査を開始しました。

たとえば Swagger は、決まったレスポンスを返すモックサーバとして動作してくれるようです。作成したAPI定義がドキュメントとして残るなら、それも良さそうに思えます。 ただし、「適切な時間をかけて返す」という部分が解決できないようで、採用を見送ることにしました。

ここでふと、 sleep(1); したいだけであれば、PHPで書いてしまえばよいのでは?と思い直し、PHPで作ってみることにしました。

PHPなら普段から書いていますので、キャッチアップのコストは不要です。

FastRouteで行為に高速なモックサービスを実装する

簡単なPHPで書けるだろうと高を括っていたため、特にウェブアプリケーションフレームワークは使用せずに実装をはじめました。

今回用意したいモックサービスのエンドポイントが8つほどあります。 いくつか似たものはあるものの、バリエーションのあるURIであったため、ルーティングがあるといいなと思いました。

そこで FastRoute を使うことにしました。これでルールの一定しないエンドポイントでも、仮にエンドポイントを増やす場合にも拡張が容易になります。ずいぶん楽になりました。

<?
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
    $r->addRoute('GET', '/users', 'get_all_users_handler');
    // {id} must be a number (\d+)
    $r->addRoute('GET', '/user/{id:\d+}', 'get_user_handler');
    // The /{title} suffix is optional
    $r->addRoute('GET', '/articles/{id:\d+}[/{title}]', 'get_article_handler');
});

こんな感じで簡単に書けました。(サンプルより引用)

あとは、事前に調査しておいた資料をもとに、エンドポイントごとのレスポンスと応答時間を設定していきました。これは地道な作業です。

一通り書き上がったところで開発環境の接続先を変更し、疎通確認を行います。HTTPリクエストヘッダを使用している箇所などのいくつかの修正を行い、ついに注文が完了できるようになりました。

これで、設置してcomposer installするだけで使えるモックサービスの完成です。

実戦投入

負荷試験実施の際には、AWSのEC2に設置し、期待通りのレスポンスを返しているかを確認しながら使いました。

試験中、何度か期待通りのレスポンスが出ないことが検知されることがありましたが、Apacheの設定値の調整などを行うことで期待通りの役割を果たしてくれました。

f:id:ymiyamura:20190122164701p:plain
これはモックサーバの設定を見直していたときのやり取りでした。

モックサービスなので、実在するクレジットカード番号を使う必要もなければ、メールアドレスの重複を気にする必要もありません。 シンプルなテストシナリオを繰り返し実行することができ、便利に使用することができました。

まとめ

  • 提供されている検証環境を使わずに自前でモックサービスを作成、使用することも、負荷試験時の選択肢としてアリだと思いました。
  • モックサービスを自由にできることで、アプリケーションやテストシナリオをシンプルにできる点も良いと感じました。
  • 今後、他の外部サービス連携にかかわる部分の負荷試験を行う際も、同じ要領でモックサービスを活用することができそうです。

最後に

これまで3回にわたり、負荷試験関連のトピックを紹介させていただきました。興味がある方は、過去の記事も参照いただけると嬉しいです。

devblog.thebase.in

devblog.thebase.in

パフォーマンスに関する改善に終わりはなく、また別の課題に向けて取り組んでいる最中です。 BASEでは、カートのパフォーマンスアップに興味がある方をお待ちしております!

herp.careers