Akatsuki Hackers Lab | 株式会社アカツキ(Akatsuki Inc.)

Akatsuki Hackers Labは株式会社アカツキが運営しています。

アカツキゲームスのインターンに参加して

はじめに

初めまして、アカツキゲームスのクライアントサイドのインターンに参加させていただいた斎藤と申します。

開発には2021/10/4~2021/10/27の期間、参加させていただいたきました。取り組んだことや感想などについて書いていこうと思います。

自己紹介

自分は、広島大学の修士1年で分散処理についての研究を行なっています。

趣味はゲーム&ゲーム制作です。サークル活動や個人などでUnityを使ってゲーム制作を行なっています。

趣味や研究での開発は行ったことはあるのですが、バイトなどの経験はなく業務での開発は今回が初体験でした。

行ったこと

自分は『八月のシンデレラナイン』(以下ハチナイ)の開発に参加しました。以下行ったタスクについて説明していきます。

放送部の一括既読機能

ハチナイには放送部というハチナイ関連のYouTubeのコンテンツや漫画などを紹介する機能があるのですが、そこに一括既読機能をつけたいというものでした。

放送部に類似した機能にお知らせという機能があり、そちらにはすでに一括既読機能がついているため、そちらの機能をこちらにも実装したいという需要です。

f:id:Aojilu08:20211027110941p:plain

f:id:Aojilu08:20211027110925p:plain

初めてのタスクだったので、最初は手探り状態で他人のコードを読むことに慣れていないものありコードを理解するのにかなり苦労しました。

ただ、お知らせの内容を放送部に移植すればよかったため、実装はあまり苦労せず実装できたかなと感じています。

このタスクは次の放送部の通知数タスクと一緒に行ったため状態についてはそちらで言及します

放送部の通知数と未読の数が異なっている件の対応

マイページには放送部のお知らせの中でまだ読んでいないものの数を表示する機能があります。この表示されている通知の数と、放送部の未読コンテンツの数が合ってないので合わせたいというのが課題でした。

f:id:Aojilu08:20211027111945p:plain

調査を開始し、未読数を取得する関数の処理を確認したのですが、未読の中で配信7日以内のものを通知数としてカウントするという処理になっていることがわかりました。

挙動を確かめてみると確かにそうなっていてちょっと感動...

意図のある実装であるためプランナーの方に報告して相談を行いました。

相談の結果、今回は通知数の挙動は変えずに未読数の方に合わせるという対応にすることになりました。言い換えると、配信後7日経過したものは読んでなくても既読をつけるということです。

実装自体はすぐに終わるものでしたが、仕様の決め方だったり、コミュニケーション面などでいい経験になったなと感じるタスクでした。

こちらの放送部系のタスク2種はレビューまで済んでおり検証待ちの状態です。

スカウトCMのテンポ改善

2つ目(実質3つ目?)のタスクはスカウトCMのテンポ改善を行いました。

新しいスカウトが追加されると、ログイン時に宣伝のアニメーションが流れるスカウトCMという機能があるんですが、このスカウトCMが複数存在する場合にテンポが悪くなってしまうのでそれを改善したいというのが課題でした。

スカウトの流れは以下のようになっています

「新選手登場!」→選手のセリフ→スカウトの紹介→ロード(複数ある場合は繰り返す)

今回具体的に行うこととしては

  • 「新選手登場!」を最初だけ表示するようにする
  • CMの合間にロードが入らないようにする

でした。

関連コードを読み進めたところ、スカウトCMを再生する機能にスカウトCMのデータを一つずつ渡していることが原因のようでした。

そのため、実装方針は以下のようにすることにしました。

  • スカウトCM再生機能にデータを一括で渡す
  • スカウトCM再生機能にもらったデータがなくなるまで再生を続ける機能をつける必要があるので、そこに2つ目以降はスキップする機能も追加する

そして実装。実装内容自体はそこまで複雑ではなかったため苦労せずに実装できました。ちょっとスキップの挙動が変になったりもしましたので修正もしました。

仕事でプログラマーをやっているとあんまりコードの量を書かないみたいな話を聞いたことがあったんですが、まさにそんな感じで、やっているタスクの消費時間だと調査>実装だと感じました。

ただ、実装が簡単に済んだのは設計が上手いことされていたからというのも感じました。ミーティングの際に、データを一括で渡すように変更するために根本の設計をいじらないといけないかも...みたいな話が出てたんですが、いざやってみると影響範囲が小さく済ませることができました。

このタスクの状態としては、検証まで完了しており10/29のアップデートに含まれるそうです。やったー!

実はスカウトCMのテンポは自分がゲームを遊んでいる時にも気になっていた箇所でした。なので担当できるのが嬉しかったんですが、実装されるともっと嬉しい...ゲーム会社で働くと楽しそうだなと感じるポイントでした。

Extraボイス入手時に何を手に入れたかわからない問題の改善

3つ目のタスクはExtraボイス入手時に何を手に入れたかわからない問題の改善です。

選手交流のページに選手ごとにミッションがあり、ミッションの達成報酬でボイスがもらえるという機能があります。このボイスについてはもらう前、もらった時ともにアイコンの表示しかないためなんのボイスをもらったのかわからないという問題がありました。

f:id:Aojilu08:20211027131051p:plain

f:id:Aojilu08:20211027131117p:plain

このタスクに関しては、最初は仕様が決まっていませんでした。そのため、まずはシンプルにアイコンの隣に名前を併記するという実装を行なってみて、それを確認して仕様を決めるという方針になりました。

実装として行うことは、新しいダイアログを追加することと各アイテムの名前を取得することでした。

新しいダイアログの追加は既存のダイアログ機能を参考にすることで実装することができました。ここでも追加のダイアログを追加しやすい設計になっていて、実装はスムーズにいきました。

アイテム名の取得の方はちょっと手間取りました。データの種類がたくさんあって、どれを取得すればいいのかわからないかったです。

ここはメンターの方に相談して、マスターデータ的なものがあるということを教えてもらいました。そのあたりを探索していると、プレゼントボックスの処理に各アイテムの名前の取得処理というまさに欲しい処理を発見できたため、それを真似ながら実装しました。

ということでアイコンにアイテム名を併記するという機能は実装できたんですが、確認したところ微妙でした。一度にみられるアイコンの数が少なくなってしまうなどの問題がありました。

仕様決定ミーティング

この実装が完了したところで仕様を決定するためのミーティングを行いました。ミーティングで話したこととしては、ボイス取得前の確認については今後実装予定の機能で対応できそうだということを話しました。そして今回の実装では、ボイスを取得した後に取得したボイスを確認できるように、ボイス一覧にnewアイコンをつけるという対応をすることに決まりました。

ミーティングの結果決まった実装内容は以下の通りです。

  • ボイス一覧にnewアイコンを表示
  • 既読セーブデータを消去するデバッグ機能の追加
  • データ引き継ぎの際に既読セーブデータが引き継がれるようにする

f:id:Aojilu08:20211027132926p:plain

まず、newアイコンの表示を行うために既読セーブデータを作成し、ボイス一覧の画面でそれを扱うという実装を行いました。ここは放送部の実装などでやったこととにていたためあまり苦労せずに実装することができました。

次にデバッグ機能の実装を行いました。デバッグ機能用のシステムを作成し、デバッグ機能の設定ファイルに追記するという実装を行いました。ここはとても追加しやすく作られておりかなり簡単に実装できました。

最後にデータ引き継ぎへの対応を行いました。こちらも変更は設定リストに1行追加するだけでした。ただ、引き継ぎコードに関しては少し懸念点がありました。

懸念点は、変更を加える前(=ボイス既読セーブデータ作成前)に作成された引き継ぎデータが引き継げなくなってしまうのではないか?という点でした。

コードを確認する限り大丈夫そうだったんですが、もし引き継ぎできなくなると大変なことなので実機での確認も行いました。ここで初めてjenkinsを利用したビルドなどを行いました。

実機での確認でも大丈夫だったためこれで実装完了となりました。

このタスクは始める前はあんまり大変そうじゃないと思っていたんですが終わってみると変更箇所が結構あってギャップを感じました。最初と比べると機能把握が早くなった感覚もありちょっと成長したかも?とか感じました。

このタスクは現在レビュー待ちの状態ですが、最終的に動作を確認して仕様に問題がなければリリースされると聞いています。

振り返り

インターンを終えての感想などを書いていこうこと思います。

学び

初めての経験が多く、学びになったことがたくさんあったなと感じています。

設計

自分はインターン前は設計の勉強をちらほらしてはいたんですがあんまり上達しないな...という状態でした。今回のインターンでは実際に運用されている設計をたくさんみることができたためすごく勉強になって、個人で作っていたゲームで早速真似してみたりしました。また、実際に使ってみた感想を持てるというのもいい経験だと感じました。実際に使うと、新しいものの追加がしやすくていい、機能が分離されていたから影響箇所が少なく済んだ、どこに機能を追加するのかわかりやすいなどの良かったポイントの感想を得ることができ、自分で設計する時に活きそうだと感じました。

良い設計ってなんですか?と言われると、今までは勉強した具体的でないものの例しか出せなかったんですが、今回の経験でこのインターンでやったあれです!みたいのことが言えそうだなと感じました。

また、どこまで設計するのかみたいな観点も学びでした。ハチナイのコードは似た処理でも実装が揃っていないこともあって、完璧なコードだ!という感じではなかったんですが、要所はちゃんとしているなと感じました。プロジェクトが破綻しない範囲でここまではちゃんと設計する。ここからはある程度勝手に実装するみたいな線引きがあるな〜と思いました。

責任

今までは、よくわからずにコピペで解決することがちょくちょくあったんですが、インターン中はそれをやるとやばいと感じ、自分が書いたコードは全て理解するようにしました。

レビューや検証でチェックはしてもらえますが、一番厳密にチェックできるのは自分なので責任を持たないといけないというのを感じました。

コミュニケーション

プランナーの方とのミーティングをすることがあり、プログラミングがわからない人とのコミュニケーションを体験することができました。

よく発生する観点として、機能の実現が可能か、どれくらいの期間がかかるのかなどの観点があること、何度もミーティングを組むと時間のロスになるのでできるだけ1回で仕様を詰めきること、タスクキルなどの抜けやすい細かい観点 などなど...色々学びがありました。

組織構造

アジャイル開発について勉強したことがあり、こういう状態が理想だ!こういう状態になるべきだ!みたいな話を理屈として知っていましたが、運用されているチームに入ることで、達成されている点とされていない点、達成が現実的でない点とできる点、達成が効果的な点とそうでない点みたいなところがちょっと感じられたかなと感じました。

と同時に経験値の不足も感じました。1つのチームを見ただけなのでデータ不足だよなとか、そもそもたくさんのチーム見るのは大変であるとか。

自分のやりたいこと

色んな人と関わることもできたため、自分がどんなことをやりたいか興味があるのかという点も理解が深まったと感じました。とりあえず興味あるかもと思った点を列挙。

  • ゲームの内容、企画職の仕事の一部
  • コードの品質とか設計
  • 効率的な組織構造
足りないもの

自分の足りない点も見えたなと感じます。コードを理解する速度が遅いとか、リファクタリングしたほうがいい気もするけど具体的にいいコードがどんなものなのか判断できないとか、設計能力不足とか...

また、就活とかでよく聞かれる得意な点というやつがあると便利なんだなというのも感じました。人より得意な分野があればそれだけ貢献できたりするみたいな...そういうのも伸ばしたい...

まとめ

とても学びの多いインターンで参加して良かったと感じています。

今回のことをこれからの活動にちゃんと生かしていきたいです。

3週間受け入れていただきありがとうございました!

AWS上の fluentd から BigQuery への認証に Workload Identity を利用する

この記事では、AWS の EC2 や ECS 上で動作する fluentd から Workload Identity を利用してBigQueryにログを送る方法を紹介します。

背景

AWS から BigQuery にアクセスする際、従来はサービスアカウントキーを利用して認証を行なっていました。しかし、サービスアカウントキーは厳重な管理が必要です。これに対して、Workload Identity を利用すれば、管理が必要なキー自体をなくすことができ、運用の手間を軽減することができます。

先日 googleauth gem 1.5 がリリースされ、Ruby からも AWS からのWorkload Identity による認証をすることが可能になりました。
rubygems.org

早速これを利用して、AWS上のEC2やECSで動作する fluentd から BigQuery にデータ送信する際の認証方法を Workload Identity にしてみます。

Workload Identity の設定

下記のドキュメントに従って、AWS のロールと GCP のサービスアカウントの紐付けを行います。
あらかじめ作成したEC2のインスタンスプロファイルに割り当てたロール、またはECSのタスクロールを、GCP上のBigQueryへのアクセス権限をつけたサービスアカウントに紐付けます。
cloud.google.com

詳しい手順は省きますが、本ブログの下記の記事でもコンソールを利用した設定方法を紹介しています。
hackerslab.aktsk.jp

fluentd のセットアップと動作テスト

Docker を利用して fluentd を動作させます。下記は最小限のサンプルですので、実際には要件に応じて buffer や fluent-bigquery-plugin の設定が必要です。
Workload Identity 用の認証情報構成ファイル(JSON)を、Dockerfile と同ディレクトリに workload-identity.json として配置してください。
なお、この認証情報構成ファイルはあくまでも設定ファイルであって認証情報ではないので、サービスアカウントキーと違ってより気軽に扱うことができますので、下記でも Docker イメージ内に単純にCOPYして配置しています。

Dockerfile

FROM fluentd:latest
USER root
RUN apk add --no-cache --update --virtual .build-deps build-base ruby-dev \
   && fluent-gem install fluent-plugin-bigquery googleauth_aws_container_credential_provider \
   && fluent-gem sources --clear-all \
   && apk del .build-deps \
   && rm -rf /tmp/* /var/tmp/* /usr/lib/ruby/gems/*/cache/*.gem
COPY fluent.conf /fluentd/etc/
COPY workload-identity.json /home/fluent/.config/gcloud/application_default_credentials.json
USER fluent
CMD ["-r", "googleauth_aws_container_credential_provider"]

※ ビルド時に googleauth gem 1.5.0以降が導入されたことを確認してください。
※ googleauth_aws_container_credential_provider は、ECSで動作させる際に必要になります。詳細は後述します。

fluent.conf

<source>
  @type forward
  port 24224
</source>

<match data.*>
  @type bigquery_insert
  @id insert

  auth_method application_default
  project your-project-name  # 適宜設定してください
  dataset your_dataset_name  # 適宜設定してください
  table ${tag[1]}
  fetch_schema true

  <buffer tag>
  </buffer>
</match>

これをdocker buildして、Workload Identity に紐付けたロールを持つインスタンスプロファイルを割り当てた EC2 インスタンス上、またはタスクロールを持つ ECS タスクとして起動します。port 24224 でデータを受信できるようにしておいてください。そして、 fluent-cat 等を利用して、

echo '{"field1":123,"field2":"test_value"}' | \
  fluent-cat -h <fluentdのアドレス> data.<テーブル名>

のようにデータを送信すると、テーブル名に指定した BigQuery テーブルにそのデータが挿入されるはずです!


ただし注意点として、googleauth 1.5.0 の時点では IMDSv2 にうまく対応できないバグがあるようです。EC2で試す際は IMDSv1 が使えるように設定し、認証情報構成ファイル作成の際にも --enable-imdsv2 をつけない (つけてしまった場合はJSONから imdsv2_session_token_url キーを削除する )必要があります。
IMDSv2 の使用 - Amazon Elastic Compute Cloud

ECSタスクロールからの認証情報の取得について

さて、ここまで ECS でも動作すると書いてきましたが、実際には素の状態の googleauth はECSのタスクロールから認証情報を取得することができません。
EC2 ではインスタンスメタデータサービス (IMDS) のエンドポイント http://169.254.169.254/latest/meta-data/ を利用して認証情報を取得します。しかし、ECSのタスクロールの場合は http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI というエンドポイントを利用して取得します。アクセスの手順も異なるので、たとえ認証情報構成ファイルのエンドポイントを書き変えても対応できません。
これは Ruby の googleauth gem だけに限らず、他言語の認証ライブラリでも同様のようです。
しかし他言語で回避策が見つけられており、タスクロール用のエンドポイントから認証情報を取得して環境変数にセットした状態でライブラリを呼べば良いことが分かっています。

参考:
aws fargate - connection error from aws fargete to gcp bigquery by using Workload Identity - Stack Overflow
Workload Identity連携でAWS(EC2/ECS/EKS)からサービスアカウントキーなしでBigQueryにアクセスする

ただし、環境変数では認証トークンが期限切れになる恐れがあります。Ruby では Module#prepend を利用してパッチを当てられるので、これを利用して googleauth が認証情報を取得しようとするタイミングでタスクロールから認証情報を取得して返却させるのが確実でしょう。
これを簡単に実現できるように、 googleauth_aws_container_credential_provider という gem を作成しました。
rubygems.org
github.com


最初のDockerfileのように、 gem install し、fluentd の -r オプションで読み込ませるだけでECSタスクロールに対応させることができるようになっています。
なお、 googleauth gem に動的パッチを当てるという内容上、今後の googleauth のバージョンアップで内容が変わると利用できなくなる可能性がある点は注意が必要です。

まとめ

EC2やECSのタスクロールを利用して、 fluentd から BigQuery へデータ送信する際に Workload Identity で認証する方法を紹介しました。
特に、現時点では EC2 では IMDSv2 対応、ECS ではタスクロール対応に注意が必要であり、その回避策を説明しました。
クラウド間のフェデレーションは仕組み自体は複雑になりがちですが、セキュアな運用がより簡単に行えるようになることを期待しています。

アカツキゲームスのサーバーサイドインターンに参加しました。

こんにちは。この度、2021/8/23~2021/9/3の2週間、アカツキゲームスの就業型インターンに参加しました。

このインターンでは、『八月のシンデレラナイン』のサーバーサイドでの業務に携わりました。

自己紹介

地方国立大学の修士2年生です。

普段は文字列を研究しており、C++やRustと戯れています。

インターンで取り組んだこと

今回のインターンでは、サーバーサイドエンジニアとして、以下のタスクに取り組みました。

管理サイトの機能追加

不具合の調査対応でユーザの情報を閲覧したり編集したりする場合は、エンジニアが作業をする必要がありました。そこで、管理サイトでできるようにしました。これにより、エンジニアでなくても対応できるようになりました。

AWSのメンテナンス情報をSlackで通知

AWSでは、稀にメンテナンスにより、インスタンスの再起動などが起こります。このようなイベントは、以下の方法で連絡がきます。

  • メンテナンスが予定されたよ!と、イベントが発行される
  • メールによって通知される

しかし、メールでの通知は、必ず行われる保証はありません。

そこで、メンテナンスに関するイベントがきた場合にSlackで通知することで、メンテナンス情報を把握しやすくしました。

構造としては、EC2やRDSなどのリソースについて、CloudWatch Events でメンテナンス情報に関するイベントをキャッチし、LambdaからそれらのイベントをSlackへ通知するようにしました。

NewRelicの導入

NewRelicとは、サーバーやインフラのパフォーマンスを分析するためのツールです。以前は導入をしていたのですが、一時的に動作が止まっていたので、開発環境で動作するようにしました。NewRelicではAPIのレスポンスタイムや、CPUの使用率、メモリの使用量などパフォーマンスを分析するためのデータを確認することができます。これにより、どのAPIが遅いのかを調査することができました。

API 高速化

NewRelic導入により、レスポンスが遅いAPIが見つかりました。そこで、高速化できないか調査を進めていきました。NewRelicではtransaction毎に、どのようなリソースへのアクセスがあったのか、また、そのリソースからのレスポンスタイムなどの詳細を確認することができます。この中で、クライアントへ返すjsonのレンダリング処理を行なっている、jbuilderが遅いことが判明しました。

jbuilderでの処理を高速化することを大まかな方針とし、どの処理がボトルネックとなっているかを確認していきました。

partialの改善

jbuilderでは、jsonでのレンダリング処理を外部ファイルから呼び出すpartialという機能があります。本APIではこのpartialを利用していたのですが、こちらは、レコードが大規模である場合に低速になります。そこで、partialの利用を回避し、実装してみました。

結果として、効果がみられませんでした。

 

N+1の改善

NewRelicでさらに調査を進めていくと、レンダリング処理の中で、DBへのアクセスが頻繁に行われていることが判明しました。これは、N+1であるような挙動をしていたので、テーブルを直接参照している処理がないか調査をしました。

すると、preloadされたテーブルではなく、直接テーブルを参照している箇所を発見したので、この処理を改善しました。

しかし、この改善においても、全体のレスポンスタイムは大きな改善とはなりませんでした。

 

時間切れ

ここまで調査した段階で、インターン期間の終了が近づいてきました。そのため、このタスクについては、サーバエンジニアチームに引き継いで調査を続けていただくことにしました。情報の引き継ぎを円滑にするために、今まで調査した内容をまとめて、Issueとして残すことにしました。APIが遅い原因は、さまざまな要素が絡まり、一筋縄ではいかないことを改めて認識しました。

まとめ

今回のインターンでは、サーバーのタスクだけでなく、AWSでのインフラに関するタスクも行うことができました。また、実際に稼働しているゲームの開発に関わることができて、とても刺激的でした。

また、アカツキゲームスの文化として発言の心理的障壁がとても小さいことを実感しました。メンターの方々のサポートも手厚く、質問に対する答えも、その答えへの辿り着く方法を教えてくださるので、課題の解決方法として学んでいくことができました。

2週間という短い期間でしたが、濃厚な時間を過ごすことができました。ありがとうございました!

Akatsuki Games Summer Internship 2021 で大規模サービスの開発に参加しました

はじめに

はじめまして、長谷川と申します。

2021/10/4 から 2021/10/29 の4週間、株式会社アカツキゲームスの『八月のシンデレラナイン』(以後ハチナイ)の開発を行うチームにサーバーサイドエンジニアとして参加させていただきました。

普段は趣味やアルバイトでWebとモバイルのアプリ開発をしたり、大学院で交通流や人流の解析の研究をしています。

 

インターン参加まで

アカツキゲームスのことはサポーターズの逆求人イベントで知ったのですが、アカツキゲームスのエンジニアはとにかく楽しそうにものづくりしてるよ〜と人事の方が話されており、興味を持ちました。

選考では主に今までの経験について聞かれ、特に友人と作ったプロダクトの開発をする時に考えていたことについて話したのがウケが良かった気がします。Railsを触るのはかなり久しぶり(&そもそも経験不足)だったので、参加が決定してから他の企業でRailsを使う短期インターンやハッカソンに参加しながら、事前準備をしてインターンに臨みました。

 

取り組んだこと

 

今回のインターンには(授業や研究で途中抜けしながら)4週間参加させていただき、主に以下の4つのタスクに取り組みました。

・管理者ツールの機能追加(Day2~Day3)

・マスターデータのバリデーション

・新規機能開発

・チャプター情報一覧取得APIのレスポンスを高速化

 

上の3つまでは軽く触れる程度にして、今回のインターン期間の約半分をかけて取り組んだ「チャプター情報一覧取得APIの高速化」について詳しく書いていこうと思います。

管理者画面の機能追加

この管理者ツールでアイテムの付与をできるようにする、というのが一つ目のタスクでした。管理者ツールは主に非エンジニアの職能の方が使うのですが、通常ユーザーに対してアイテムを付与するというのは強力な機能なので、手違いが起きないように運用フローを整えてもらう必要がありました。この部分でエンジニア以外の方とコミュニケーションを取ったのですが、こういう体験は技術とはあまり関係がないながら業務以外では体験しづらいのでいい経験になったなと思います。

 

マスターデータのバリデーション

(ハチナイにおける)マスターデータとは、選手の能力やショップの交換レートなどのユーザーの操作によって変化しないデータのことです。これと対になる概念として、獲得した経験値や所持しているアイテムなどのユーザーデータがあります。

ハチナイでは、このマスターデータに対して不正な値をもった選手や、イベントが発生しないようにバリデーションをかけています。不具合を未然に防ぐだけでなく発生した不具合が再度発生しないようにするのもマスターデータのバリデーションの役割です。今回のタスクでは過去に起こった不具合の原因を調査し、その不具合が起きないようにするためにバリデーションを追加しました。不具合の原因の調査は、1つ目のタスクと同じようにエンジニア以外の方とコミュニケーションをとりながら進めていったのですが、コードだけからは読み取れない運用ルールなどを知ることができて、コミュニケーションの大切さを学ぶことができました。

 

新規機能開発

2つ目のタスクが終わった時に「新規機能開発に興味ありますか?」とメンターの方に聞かれ「楽しそう!やりたいです!」と答えると、メンターの方が実際に業務で進めている新規機能の開発の一部分を任せてもらえることになりました。(新規機能については、公開されていない情報をかなり含むので詳細に触れることはできませんが、)テーブル定義、実装方針検討、エンドポイントの決定、API作成、テストを書く、など新規機能開発の一連のフローを経験できました。4つのタスクの中では最もユーザーにとってわかりやすいタスクだったので、自分が開発に参加した機能が実際にリリースされるのが楽しみです。

 

チャプター情報一覧取得APIのレスポンスを高速化

これが一番時間をかけて頑張った、かつ成果を出せたと思っているタスクです。このAPIはメイン画面から、試合ボタンを押した時などに叩かれるチャプター情報の一覧を返却します。実際のゲーム画面で言うと、例えば

 

f:id:t_hase_aktsk:20211101083039p:plain

から試合ボタンを押して

f:id:t_hase_aktsk:20211101083045p:plain

へ遷移するときに叩かれているAPIです。確かに言われてみれば、プレイしていても結構遅い。と言うわけで、まずは速度計測から始めました。僕の環境でのレスポンスタイムの計測結果が以下でした。

Completed 200 OK in 3957ms (Views: 2452.5ms | ActiveRecord: 251.4ms)

約4000ms。。。!早くしなくちゃ!と思い早速改善に取り組みました。

ViewsとActiveRecord以外の部分で1300msくらいかかってるのは流石に遅すぎない。。?Controller層の処理が怪しそうと思いそのあたりの処理の速度を測定するとビンゴ!チャプターに関連するアソシエーションを取得するpreloadが大量に連なっている所がとても重くなっていました。(僕はpreloadはN+1を解決するためにするんだから早くするためのモンだと思ってましたが、ハチナイくらいのサービスになるとレコードの量がすごいので、気軽にpreloadすると重くなってしまうんだな。。)その中でも特に遅い部分を調査していると、クリアスターの有無を計算する所が重くなっているようでした。ここはマスターデータだけで計算できる部分だったのでキャッシュに持たせるのが有効そうだと考え、早速実装してみると

Completed 200 OK in 2659ms (Views: 1866.2ms | ActiveRecord: 229.5ms)

といきなり30%ほど改善できました!

この時点まだインターンの残り期間が1週間あったので、さらに高速化したい!とさらに調査を進めました。

 

というわけで、遅い処理を特定するためにログを見ていると怪しい箇所をいくつか発見。bulletでは検知できない明示的でないN+1が発生しています。

ここのN+1を解消すると

Completed 200 OK in 2330ms (Views: 1739.6ms | ActiveRecord: 73.0ms)

と少し早くなりました。

また、遅い処理で改善できそうな部分を見ていくと、キャッシュをwriteした後は使われないアソシエーションがpreloadされているのを発見したのでそこのpreloadを削除。ここでインターンの残り期間がほとんどなくなっていたので、PRを短時間できちんと出せるような細々した改善点を探すためにログが汚くなっているところを見ていくと、同じようなN+1や無駄なキャッシュのreadを発見しました。これらもなんとか期間内に解消して少しだけ速度改善。これらは速度改善という点で見ればあまり結果は出なかったですが、ログは綺麗な方が気持ちが良いので達成感はありました。

最終的には

Completed 200 OK in 1871ms (Views: 1554.7ms | ActiveRecord: 28.8ms)

というレスポンスタイムになり、最初の4000msと比べると50パーセント以上の改善になりました!

 

業務を終えて&感想

成果発表

これにてインターンとしての業務は終わり、最後に成果発表会を行いました。

成果発表会では今までお世話になった方々からFBをいただけるのですが、直接は話していなくてもslackで僕のtimesチャンネルを見て、気にかけてくださっていた社員さんたちからも温かいコメントをいただいて、思っていたよりたくさんの方に見守られてこのインターンを走り切れたのだなと温かい気持ちになりました。また、「速度改善というタスクは新規機能開発などと違い、ユーザーに分かりやすいFBをもらえるようなものではないけど、サービスにとってすごく価値があることだからチームの私たちからたくさん感謝を伝えたい」というようなことを言っていただき、嬉しかったし、仕事の価値を認め合える空気があるというのがすごくいい環境だなと思いました。

感想

このインターンでは、人生で初めて大規模な開発に関われたり、色んな職能の方とランチしたりミーティングしたりなど、すごく良い経験をすることができたなと思います。またコードを書くばかりがエンジニアの仕事ではなく、エンジニア以外の職能の方とのコミュニケーション、仕様検討、原因調査などもエンジニアの大切な仕事であることを学べたのはすごく良かったなと思います。

また、メンターの方は自走を促すけど、困ったことがあればすぐに相談に乗ってくださり、僕にとって安心して挑戦できる&成長できる環境を整えてくださいました。この場を借りて改めて感謝を伝えたいです。本当にありがとうございました!

 

 

 

アカツキゲームスのインターンでAPI高速化と新規機能開発に取り組みました

こんにちは! 2021/8/10〜2021/8/27の3週間にわたってアカツキゲームスのサマーインターンに参加させていただきました、細谷と申します。

今回のインターンで取り組んだことや学んだことについてまとめます。

自己紹介

東北大学大学院 情報科学研究科に在学中の修士1年です。研究ではコンピュータビジョンや機械学習を扱っており、趣味でWebフロントエンド・バックエンドを幅広く触っています。

よく書く言語はTypeScript、Python、Golangで、最近は新規Webサービスの開発をしている関係でソフトウェア設計などの学習をしています。

インターンで取り組んだこと

今回私は、『八月のシンデレラナイン』(以後ハチナイ)というゲームの開発チームにサーバーサイドエンジニアとして参加しました。

ハチナイのサーバーサイドは主にRuby on Railsを用いて開発されています。私はRailsでの開発経験がなく、ある程度の予習が必要とされました。そのため、経験があり言語として近い性質を持つPythonとの共通点を捉えつつ、ActiveRecordなどのRails特有の知識を一通り学習してからインターンに臨みました。

APIの高速化

最初に取り組んだのは、「購買部」内にあるアイテム変換機能に関するタスクでした。ここではナインスターや各種変換コインを用いてアイテムを入手することができますが、その際に発生する「現在販売中のアイテム」を取得する処理が重く、アイテム変換への画面遷移が少し遅いという問題がありました。

この処理は具体的には、「どのアイテムを用いて交換できるか(カテゴリ)」という情報と、「各アイテムを何と交換できるか」という情報を取得する2種類のAPIが用いられています。そのため、N個のカテゴリ全てに対してそれぞれで交換できるアイテムを取得すると、全体ではN+1回のAPI呼び出しが行われることになり、無駄が多い状態になってしまっていました。

設計としてはいわゆるRESTfulなAPIでしたが、これらで取得できる情報を1つにまとめることで端末とのやりとりやデータベースへのアクセス回数が減り処理が高速になると考えられます。そこで、既存のAPIとは別に、「アイテム交換で現在販売中のアイテム」全てを取得できるAPIを作成しました。

改善の結果

呼び出す必要のあるAPIを1つにまとめた結果、負荷試験環境において約3.5倍の処理高速化に成功しました。この改善によって、アイテム変換機能への遷移が高速になることが期待されます。

スキルの入れ替えに関する新規機能開発

2021年8月現在の仕様では、各選手ごとに習得できるスキルの個数に上限があり、別のスキルを習得したい場合は既存のスキルのどれかと入れ替えるようになっています。この際、付け替えによって外したスキルを再度習得させたいときに、新しく習得する場合と同様にアイテムを消費する必要があります。これは特に、UR選手で投手と野手を切り替えたい際に不便を強いる形となっています。

そこで、「過去に習得したことのあるスキルを任意に入れ替えることができる」ようにスキルの習得に関する仕様の変更が提案されていました。この実装として、選手のスキルごとに「過去に習得したことがあるか」を新たに保存するようにし、したことがあればアイテム消費なしでスキルを入れ替えることができるようにしました。

チーム内でのやりとり

このタスクは同時期にクライアントサイドのインターンで参加していた方と協力して実装しました。また、仕様の変更に関わる部分であったため、詳細な仕様を確認するためプランナーの方ともやりとりを繰り返しました。結果としては、選手育成の画面にてスキルを入れ替える機能を実装し、クライアントサイドとの結合テストまで行うことができました。

※画面は開発中のものであり、実際の仕様とは異なる場合があります

インターン期間内で得られたこと

運営中のゲームタイトルの開発に携わる、ということ

実際にチームのエンジニアの一員として、ハチナイの開発に携われたのは非常に貴重な体験だったと思います。ゲームの体験を壊さないためにも、既存機能の改修には特に慎重になる必要があり、そのような考慮はこれまでの個人開発では得られなかったことだと思います。また、プランナーの方やクライアントエンジニアの方とのやりとりの間で認識の齟齬が生まれないようにうまく言語化することも開発を進める中で得られたことでした。

チームの一員として動く

開発に携わる間にメンバー、一人一人に信頼が置かれているのとともに、チームやプロダクトのために責任感を持って動いているのだと感じる機会が多かったです。

3週間という短い間でしたが、手厚いサポートに支えられ、成長できる機会をたくさんいただくことができました。ありがとうございました。