この記事は?
@cosmeのPC版トップでは今年6月に全ての画面上のUIとAPIに関して刷新的なリプレースが行われ、
それに伴ってバックエンドはNode.jsに統合されました。
10年越しのリプレースとなり、大変骨が折れる作業でしたが、なんとか大きなバグもなくリリースすることができました。
現在、@cosmeのMonthly Active Userは1700万を超え、この負荷はNode.jsやmemcached、kafka、ロードバランサーなどの諸技術を用いることによって捌くことができています。この記事ではリプレースに伴って行った負荷試験と速度改善、および@cosmeメディアが負荷対策と速度改善に用いている諸技術を皆さんと振り返りたいと思います。
負荷試験や速度改善に興味のある方はぜひご覧ください!
負荷に関する基本的な用語
基本的な用語をおさらいしておきましょう。
ここは復習パートなのでわかる方はスキップしてください。
・システムの性能評価の基本
レイテンシー:処理にかかる時間
リクエストを送ってからレスポンスを受け取るまでの時間
例:APIリクエストが200msで返ってくる
ユーザー体感に直結する指標
p50, p95, p99などのパーセンタイル値で表現
スループット:単位時間あたりの処理量
単位時間あたりの処理量
例:1秒あたり100リクエスト処理(RPS: Requests Per Second)
システムの処理能力を示す指標
TPS (Transactions Per Second) としても表現
ワークロード:システムにかける負荷の内容
例:「1秒間に1000ユーザーがログイン」「商品検索が1日10万回」など
実際に起こる負荷を想定したもの
Error Rate(エラー率):
ER = (失敗したリクエスト数 / 全リクエスト数) × 100%
・負荷試験における主な設定項目
スレッド数(同時ユーザー数)
10スレッド = 10人が同時アクセス
各スレッドは1人のユーザーを模擬
Ramp-Up期間(ユーザーの増え方)
例:スレッド数10、Ramp-Up 100秒の場合
- 開始0秒で1人目がリクエスト開始
- 開始10秒で2人目がリクエスト開始
- 開始20秒で3人目がリクエスト開始
...と10秒ごとに100秒までユーザーが1人ずつ増加
ループ回数(繰り返し回数)
各ユーザーが同じ操作を何回繰り返すか
前の操作が終わったら即座に次を実行
どうやって負荷を測定するのか?
@cosmeのシステムではNewRelicを活用することで、
日々負荷を測定することができています。
ところで、今回のリプレースに伴う負荷テストとして、jmeterを使って通常時の負荷からピーク時をはるかに超える負荷 を掛けて行っています。
通常時のパフォーマンスは日々測定しておく傍ら、負荷テストでは想定以上の負荷をかけることによって、どこまでの負荷を耐えられるシステムであるか?がわかり、通常の状態では露出しなかったシステムパフォーマンスのボトルネックが露呈してくるため、そこをNewRelicなどの分析ツールと合わせて見ていくことによって、改善点を特定することが可能です。
どうやってパフォーマンスを改善するのか?
システムリプレースに伴って@cosmeのパフォーマンス改善が行われた結果として、中央応答速度を最大30%程度ほど向上させることができました。
今回のリプレースに伴っては、新たにNode.jsを採用したためPromise.all によって非同期処理を並列に行ったことが速度の改善に役立ちました。
また、JMeterで負荷をかけたときのそれぞれのAPIのパフォーマンスを分析してみて、@cosmeトップ画面で実行されるSQLに関してもボトルネック分析を行い、インデックス等の全体的な見直しを行いました。
このように、数値を測定しつつ、ボトルネックを特定し、その部分の改善をしていくという流れがパフォーマンス改善の基本になってきます。
@cosmeメディアの負荷戦略
@cosmeのバックエンドは前述の通り、Node.jsのI/Oバウンドに強い特性を活かして高速に大量トラフィックを裁くことができています。
@cosmeメディアを支える技術はNode.jsと周辺技術から成ります。
特筆すべき負荷戦略には次の3つがあります。
1つ目はAWS ASGの使用による局所的な負荷対策です。
各サービスへの局所的な負荷に対しては、そのモジュール専用のASGを用意することで負荷に備えることができます。
2つ目は、memcachedをキャッシュサーバーとして使うことでの負荷対策です。memcachedを使ってDBへの負荷を抑えています。
3つ目はkafkaによるさらなる負荷の対策です。例えば、会員情報を返すAPIのように負荷が甚大だが変更に伴って即座な情報反映が必要な箇所はKVSで負荷を抑えつつ、情報反映があった時はkafkaが情報を受け取ってKVSのキャッシュを破棄更新することで、会員情報APIへの参照を最低限に抑えつつ、リアルタイムな情報を高速に返すことが可能です。
詳しくは著者による以下のLTをご覧ください。
終わりに
メリークリスマス。皆さんが幸せなクリスマスを過ごされますことを!