マルチプレイの負荷試験で気をつけなければいけないこと

R.Y.氏(以下、R.Y.):次に、負荷対策や負荷試験の話をしようと思います。

(スライドを示して)先ほどもあった話ですが、この負荷試験の中で、PrizmサーバーやOpen MatchというマッチメイキングOSSなどや、マルチプレイに関わる部分で「これは本当にリリースに耐えられるのだろうか」みたいなところを検証したいということでやっています。そのための試験を特にPrizmチームが注目してやっていたという話です。

この負荷試験についてですが、先ほど話があったとおり、実際のユーザーに近い挙動で試験をしたいというモチベーションがあります。この理由としては、「マッチングして、ゲームをプレイして、マッチングして」というサイクルでプレイヤーが問題なく遊べるかを検証するのがそもそもの目的なので、きちんとやりたいよねというところがあります。

なので、ユーザーの動きに近いシナリオを実装する必要がありました。逆にいうと「マッチング中にマッチングをあらためて開始しない」「相手のターン中に自分が行動した時のメッセージを送らない」ということをきちんと制御する必要があるということです。

負荷試験で苦労したこと botを実装する過程で出会った課題

そういうふうにbotを作って負荷試験を実施していくところで、いくつか苦労したポイントがあるので紹介します。

1つ目はシナリオを作成するためのログ収集であった課題です。「botを作りましょう」という話が来た段階では、ログ収集をする方法がそもそもPrizmとして整備されていなくて、すごく原始的な方法でなんとかするしかありませんでした。

(そこで)どんなことをしたかというと、Unity側にログを仕込んで、吐き出されたEditor.logをawkして、さらにawkしきれていない情報を手で削ってということをして、なんとか通信の流れを追えるようにしていました。

この手法はそもそも面倒くさいですが、それ以上に他のメンバーに「別のシナリオを作って」と依頼しようとする時に、「あれをして、これをして、あれをしないといけないんだけど」みたいな話をしなきゃいけなくて、すごく大変です。情報量が増えてしまったり、「そこがうまくいかないんだけど」みたいな(話をしなければいけないなど)、シナリオを取りたいだけなのに、本質的ではないポイントでつまずくところが課題でした。

そこで、負荷試験が落ち着いたあとに、Prizmサーバー側に機能を追加しています。メッセージを受信した時に共通で呼ばれる処理を実装できるようにして、「こういう処理が呼ばれました」ということをログ出力しやすい機能を追加しました。

Cloud Loggingを使っているのですが、これでログを吐き出すようにするとクライアント側で見るよりも、サーバー側で見たほうが絞りやすくなっているので、流れとしてはサーバー側にログを仕込んでCloud Loggingでログを絞り込むようなかたちでシナリオを集められるようになったのではないかと思っています。

「なったのではないか」と言うのは、実際にまだ動かしているわけではないので、本当にうまく動くのかがわかりません。(ただ)少なくとも「このような機能が必要なんだ」と発見できたのは収穫なのではないかと思っています。

次に、botのゲーム進行状態のハンドリングについてのお話をします。どういうことかというと、マッチングをしているのか、インゲームなのか、インゲームの中でも自分のターンなのか、相手のターンなのかといった進行状態をbot上で再現するのがけっこう大変だったという話です。

大変そうだということは最初から思っていたので、状態遷移図のようなものを書いて実装することはしていて、正常系はけっこううまくいった感触がありました。

ただ、正常系よりも異常系がけっこう大変だと感じています。例えば、マッチングでうまくいかなかった時にどういう挙動になるのかや、ターン制(のゲーム)なので、相手の行動を待っている時に通信相手がうまく動かなくなってしまって、待ち時間がタイムアウトしてしまったり。あとは、通信相手のメッセージが届く・届かないで遷移が変わるような挙動があったのですが、そこでメッセージがうまく届かなかった時の挙動などで、いろいろつまずきがありました。

例えばでいうと、相手が移動した結果「目的地に着きました」と(いうメッセージが)送られてくるケースと送られてこないケースがある。目的地に到着した時には「相手はもうゲームをクリアしたんだな」、到着していない時は「相手はまだ次のターンがあるんだな」みたいに遷移が変わるケースがあるのですが、その時に「目的地に到着した」(というメッセージ)が遅れて届いてくると、「あぁ、もう大変だ」となってしまう感じです。

負荷試験で苦労したこと 負荷試験を実施する過程であった課題

次に、負荷試験を実施する過程であった課題についてお話をします。

1つ目は、負荷をかける規模を大きくすると動かなくなる問題です。これは先ほどの話にもありましたが、規模を大きくするたびに問題が出ることは覚悟してスケジュールを組むようなことをしなければいけないんだなと感じました。

もう1つ、マッチングがうまくいかない問題がありました。これも先ほど少し話がありましたが、マルチプレイを見ているチームとしては、これはけっこう重い問題だと感じました。

なんならインゲームやリアルタイムサーバー自体の問題よりも、マッチングの問題を解消している時間のほうが長かった印象があるので、マッチングはけっこう難しいんだなという感想を持ちました。

ただ、マッチングはやることがけっこう似ているので、この先、知見を溜めていってスムーズに解決できるようになるといいなと考えています。

負荷試験を実施してみてどうだったのか?

次に、負荷試験を実際にやってみてどうだったのかという話をします。

まずはリソースの割り当てについての話です。リアルタイムサーバー、Prizmサーバー1台あたりにどれだけの負荷をかけてもいいのかを検証している時に当たった課題です。

Podのリソース、例えばCPUの使用率などはけっこう余裕があるはずなのに、負荷試験の(中で)、例えばクライアントから送られてくる通信のレイテンシがなぜかすごく遅くなっていて。「なんでなんだろう?」と考えていました。その原因がPodのリソースの使用量ではなく、Podが載っている1個下のレイヤーのノード単位でのリソースが逼迫していることだったことがありました。

気づいてみれば「それはそうだろ」という話ですが、仮想化されていることもあって、ついついPodばかりを見てしまうなと思いました。「ノードの単位もちゃんと見ないといけないんだな」というようなことを1つの学びとして得ました。

次はTLSのハンドシェイクの話です。PrizmではTCPの暗号化にTLSを使っているのですが、このTLSのハンドシェイクが思った以上に重いということがわかりました。

どういうことかというと、定期的かつ断続的に負荷試験のスコアが悪くなる。「たまにすごく調子が悪いんだよ」みたいなことがありました。 その原因をいろいろ掘っていって、最終的にクラウドのプロファイルを見たところ、今までTLSのハンドシェイクはぜんぜん目立っていなかったのですが、TLSのハンドシェイクが負荷試験の中で一番重い処理になるような位置に出ていて、「あ、TLSって重いんだ」と感じました。

これは、ゲームの処理が軽くて、相対的に負荷が高くなったところがあるのではないかと思っています。

対策として、そもそもTLSのハンドシェイクに合わせてスペックを調整しようということや、プレイヤーの流入のペースを調整しようというようなことをやりました。TLSのハンドシェイクがたくさん来るとツラいから、「そもそもユーザーが1つのサーバーにあまり集中しないようにすれば、ハンドシェイクを同時に扱う量が減って、ツラくなくなるよね」みたいな作戦でやって、これはけっこう刺さったと感じました。

負荷試験の経験は次に活かしていく

負荷試験まわりのまとめです。マルチプレイのゲームを問題なくプレイできるかを確認するために、負荷試験を実施しました。

この時には実際のゲームプレイに近いシナリオを用意する必要があって、その負荷試験の準備や実際に実施した過程で、いくつか問題であったり知見であったりを見つけることができました。

また、負荷試験を実施した結果、意外なところに落とし穴があったこともわかったので、今後に活かしていきたいなと思っています。

「マルチゲームの自信ニキの集団」のようにならないといけない

最後に、Prizmチームとして何をどう考えたかといった話をして終わりにしたいなと思います。

すごく思ったこととしては、「ライブラリとしてどうだ」という(こと)より、むしろゲーム作りにもっと強く関わっていきたいと思いました。

今まではPrizmというライブラリを作る「ライブラリ屋さん」という立ち位置でやっていたのですが、ゲームのリリースが近づくにつれて、Prizmでマルチプレイのゲームを作るにはそういう基盤の部分だけではなく、例えば通信の頻度みたいなところやアプリゲームの仕様など、実装のようなところも難しいし、そこをきちんとやっていかないと良いマルチプレイのゲームは作れないんだなと感じたので、そこをやっていきたいなと感じました。

そのためには、チームがそもそも「ライブラリ屋さん」ではなく、「マルチゲームの自信ニキの集団」のようになっていかなきゃいけないんだというところで、自分たちもそうだし、ライブラリを使ってゲームを作っている側にも、マルチプレイのことだったらライブラリに関わっていなくても「仕様のここらへんはどうですか?」みたいなコミュニケーションを取る相手として捉えてもらえると、すごくうれしいなと考えました。

ということで、最後はちょっとよくわからない感じになってしまいましたが、ここで発表を終わりにしたいと思います。ありがとうございました。