Eコマースプラットフォームの成長を支える負荷試験の取り組み

f:id:ymiyamura:20190122163945j:plain

BASEでサーバサイドエンジニアをしている宮村です。

つい最近まで、主にEコマースプラットフォーム「BASE」の決済領域の開発をしていました。決済領域は、いかなる場合でも安定稼働が求められる領域です。いかなる場合でもというのは、BASEが対応する各種決済方法やクーポン、ショップコインなど機能の組み合わせという意味でもそうですが、アクセス集中による高負荷に対しても、同様に安定が求められます。

前者に対しては、弊社東口からユニットテストの取り組みを以前紹介させていただきました。今回は、後者への取り組みとして、負荷試験の取り組みを紹介させていただきたいと思います。

動機

「BASE」は「Eコマースプラットフォーム」ですので、主として提供している機能の一つに、「カート」の機能があります。主として提供しているということは、サービス開始当時から、この機能を提供させていただいているということでもあります。

f:id:ymiyamura:20190122164228p:plain
リリースした頃のBASE

おかげさまで多くのショップ様、購入者様にご利用いただけるようになり、その性能面について把握、改善することがこれまで以上に求められる場面が出てきました。

改善するためには、改善したことが評価できなくてはいけません。購入に関する定量的な指標をおいて、計測することにしました。

準備

環境

前提として本番相当のものを用意することにしました。いくつかの懸念があったのですが、下記のようにクリアすることができました。

1. コスト面の課題

使うときだけ簡単に試験環境を立ち上げられる仕組みを作ったり、関連している諸サービスのうち今回のシナリオで必要なものだけを本番相当にするなど、コストを抑える工夫をしました。

2. 外部サービスとの連携

カートシステムでは、外部の決済サービス等との連携を行っています。負荷試験といっても、外部サービスへの過負荷は望ましくありません。(サービスによっては許可されない場合もあります。)今回は内部の性能試験にフォーカスしたかったこともあり、外部サービスを模したモックサービスを構築してそこに接続するようにしました。

また、試験中の状況の把握や、発生した異常の解析のため、監視サービス等も、本番同様のものを導入しました。

ツール

試験ツールには、諸条件を考慮してApache JMeterを使用しました。

セッション管理やページ遷移を伴うシナリオが必要だったこと、負荷テストサーバーのスケールが容易にできること、メンバーの経験などを考慮してツールの選定を行いました。(JMeterの活用については、別の記事で述べられればと思います。) 結果として、機能や習熟の不足などによる大きな問題もなく、試験を行うことができました。

シナリオ

カートに商品を投入してから、購入者情報の入力、購入完了までの数画面を遷移するものとしました。カート内は購入者情報など入力される値も多いのですが、JMeterの「記録コントローラ」を使用することで比較的手をかけずにシナリオを作ることができました。

実施

役割分担

今回の負荷試験は、主として3名のエンジニア(アプリケーションエンジニア2名、SRE1名)で進めました。

シナリオ構築やモックサービスの構築、シナリオ実行、レポーティングなど、主にアプリケーションに関する部分をアプリケーションエンジニアが担当し、環境構築などの部分を、SREが担当しました。

それぞれがやるべきことに集中できたことで、環境構築の工夫やモックサービスの構築などプラスアルファの部分にも力を割くことができたことはとても良かったように思います。

さて実行

シナリオを実行してみると、いくつかの課題が発生しました。

モックサーバがボトルネックになっていた!

これは元々、様子を見ながら調整する予定でした。LBとappサーバのログを確認し、接続数を増やして安定しました。

f:id:ymiyamura:20190122164441p:plain
SREのメンバーがここをサッと見てボトルネックを特定してくれました

購入ではないところがボトルネックになっていた!

当初のシナリオでは、まず商品画面にアクセスして、カートに商品を投入するということをやっていたのですが、商品画面に使っている外部サービスが開発用のスケールのものでした。今回のシナリオでは不要なアクセスだったため、本当に必要な画面遷移に絞ることで解決しました。

f:id:ymiyamura:20190122164540p:plain
New Relicで、遅くなっている処理を特定しました

想定したところと違うボトルネックが発覚した!

DBがボトルネックになるかな?と想定していたところ、Apacheがボトルネックになっているような挙動を見せました。どちらも本番相当の環境であるため、当初想定していた負荷の強度をクリアしていたこともあり、このあたりが限界であると結論づけました。いくつかの設定を変更して追加の試験を行い、即座に反映できるような変更点は見つけられませんでしたが、次の改善への取り掛かりとして知見が得られました。

f:id:ymiyamura:20190122164603p:plain
Mackerelで監視

f:id:ymiyamura:20190122164639p:plain
DBエンジニアの植木に教えてもらったRDSのPerformance Insightsがとても便利でした

実施中の様子

Slackで実況しながら、わいわいやりました。 負荷を増やしていきながら、エラーなく処理を完了している様子や、謎のエラーが発生していることを随時報告するようにしました。隣の島のリードエンジニアがさっくりと原因を指摘してくれたり、SREのメンバーがインフラを調整してくれたり、次々に現れる課題が攻略されていくさまに感動と感謝でいっぱいになりました。

f:id:ymiyamura:20190122164701p:plain

結果

負荷試験を実施すると決めてから2ヶ月程度で結果を出すところまで行うことができ、定量的なレポートを社内に共有できました。 また、並行して進めていた改修についても、前向きな効果がありそうだという結果も得ることができました。 トラブル以外では決済領域が目立つことは少ないのですが、前向きな成果を共有できたことは、チームにとっても良かったなと思いました。

まとめ

  • 負荷試験を実施することで、システムの性能について定量的な指標を得ることができました。
  • 性能に関する改善を行うにあたり、その効果が見込めることを改修前に示すことができました。高負荷状態は常に発生するものではないので(残念ながら)、同等の環境で再現させることで、その効果や副作用がないことを確認したうえでリリースの判断をすることができました。
  • 高負荷状態を再現させる環境を手に入れたことで、安心してサービスを成長させていく土台ができたかなと思います。他の箇所で高負荷に起因する課題が発生した場合にも、知見と環境を活用して対応していけるものと期待しています。

最後に

本記事では、BASEで実施した負荷試験の取り組みについて紹介させていただきました。負荷試験に取り組むにあたり、特定のツールの使い方以上の実践的な情報がまだ少ないなと感じるところもあり、一つの実践例として本記事が少しでも参考にしていただければ幸いです。 また、本文では簡単な紹介になってしまいましたが、JMeterの活用やモックサーバの構築については今後別の記事で紹介できればと思います。

BASEでは60万ショップの決済を支えるエンジニアを募集しています。支えるだけでなく、より良い決済システムにしていく挑戦をやっていきますので、興味のある方はぜひ下記よりご連絡ください!

open.talentio.com