feature image

2023年3月29日 | ブログ記事

traP Collectionでのダウンタイムほぼ0のAPI移行

この記事は新歓ブログリレー2023の21日目、SysAdTechBlogの第11回目の記事です。

こんにちは。19B(23M)の@mazreanです。普段はSysAd班でサーバーサイドの開発・運用を行なっています。

@BOT_pika_test、かわいそう…どこの悪魔がこんなことを…そう、私です!

22BによるtraQ bot制作ブームについて
これはtraP 新歓ブログリレー2023 19日目の記事です。 22Bの @ikura-hamuです。SysAd班に所属して部内サービスの開発・メンテナンスをしたり、ゲーム班に所属してゲームを作ったりしています。 traQって何? traPには、SysAd班が運用しているSNS「traQ」があります。このサービスはtraPのオンライン上の部室となることを目的として作られており、部員たちは日々このSNS上で会話をしています。traQについての記事はこちらをご覧ください。 traQ - 東京工業大学デジタル創作同好会traP『デジタル創作同好会traP』は、東京工業大学で活動するデジタル創作…

この記事では、私がtraPのSysAd班で開発・運用を行っているtraP Collectionというゲームランチャーで行った、REST APIの移行について話していきます。

この記事は新歓ブログリレーの記事ですが、新入生が内容を理解できることを想定している記事ではないです。理解できたあなた、是非SysAd班に入ってください。良い経験ができると思います。

SysAd班では毎年Webエンジニアになろう講習会というプログラミング初心者がWebエンジニアとして必要な知識と能力を身に着けるための講習会を行っています。今はこんな記事を書いている自分も大学に入ったときはプログラミング経験がなく、Webエンジニアになろう講習会で学生エンジニアとしての一歩を踏み出した一人です。

新入生にはなんとなく「SysAd班に入るとプログラミング初心者でもこんな経験ができるようになるのか」ということが伝わってくれればうれしいです。

ゲームランチャー traP Collection

traPはゲーム開発を行うサークルとして生まれたこともあり、毎年多くのゲームが製作されています(作品紹介から見れます)。

traP Collectionはこれらのゲームをサークルの外の方により手軽に遊んでもらい、部員の創作活動へのモチベーションをさらに高めるためのサービスとして開発されました。

traP Collectionができる前は、traPで開発されたゲームを遊ぶためにはそれぞれのゲームのブログ記事で公開されたリンクからゲームのインストーラーを実行し、インストールする必要がありました。traP Collectionにより、ゲームランチャー1つをインストールするだけで、traPで開発されたゲームをダウンロード、起動することができるようになりました。

このランチャーをコミックマーケット(以下コミケ)で販売したり、工大祭での展示に利用することで、traPで開発されたゲームの発信に利用しています。

工大祭にてゲーム展示イベント「ゲームドーーン」を開催します
10月29日30日の土曜日と日曜日に行われる工大祭において、traPはゲーム展示イベント「ゲームドーーン」で参加しています! 会場は西9号館W933教室です!入口に案内スタッフもいるので安心! traP内製のゲームを展示するほか、グラフィック班の画集やSysAd班の技術本、有志によるブース出展など、traPの魅力を詰め込んだイベントとなっております。 今年の工大祭は予約制となっておりますが、ぜひお越しください! 本記事では「ゲームドーーン」で試遊できるゲームをまるっと簡単にご紹介いたします! ClimblocK落ちものパズルしながら、上へ上へと昇って行こう! 自動で動くキャラクターの道を君の頭…

構成

traP Collection全体の構成の概要です。このうちの管理用Web UI、ランチャー、APIサーバーがtraP Collectionのコンポーネントです。

ランチャーはAPIサーバーからゲームの一覧などの情報を取得し、Object Storageからゲームの実行ファイルなどをダウンロードすることで、ゲームの管理を行います。このランチャーからは一切APIへの書き込みのリクエストは発生しないのが、移行の際のポイントとなります。

部員によるゲームの追加はWeb UIからAPIサーバーを通して行えるようになっています。この際の部員の認証は、部内SNS traQでのOAuthを利用することで行っています。

APIサーバーでのゲームに関する情報などはデータベース(MariaDB)に保存しています。

APIサーバーの詳細

今回の記事の主役となるAPIサーバーについて、もう少し詳しく解説していきます。

APIサーバーは使えるリソースの制限やSysAd班内での使用技術の統一性などを考慮しGo言語で実装しています。

また、構成図を見てわかるようにAPIサーバーはObject Storageや認可サーバーなどの多くのコンポーネントと接続しています。また、現在SysAd班内ではObject StorageではOpenStack Swift互換のストレージからS3互換のストレージへの移行や、認可サーバーの役割をtraQから内製の部員管理サービスportalへ移すことなどが検討されており、各コンポーネントを柔軟に入れ替えられる必要がありました。これらの事情を鑑みて、APIサーバーではドメイン知識と外部コンポーネントとの接続部分を分離し、外部コンポーネントの変更に強いクリーンアーキテクチャをベースとしたアーキテクチャを採用しています。

APIの移行の経緯

旧APIは自分がサーバーサイドの開発を始めたばかりのころに作ったこともあり、整合性や運用の継続の観点で問題がありました。具体的には、ランチャーで必要となるゲームの紹介画像などがない状態になりうる、同一のゲームの紹介画像が複数回アップロードされストレージを無駄に使用する、などです。

このような問題をエラーを返すなどで逐一対応していくには限界があり、開発速度や安定性の低下を招くおそれがあることから、APIの設計を変更することで対応することになりました。

新APIの設計・実装

移行をするためには新APIを設計・実装する必要があります。

設計は、旧APIで発生した整合性の問題を踏まえ、ゲーム情報などがランチャーから見えてはいけない状態とならないのを最優先にした設計としています。また、旧APIで追加されたデータの扱いについては細心の注意を払い、API設計のレビュー時には過去のデータが関わる変更全てに旧APIで追加されたデータの扱いを併記しています。以下の新API設計時のPull Requestを見ると、注意の払い具合はわかりやすいと思います。

API v2 by mazrean · Pull Request #406 · traPtitech/trap-collection-server
v2のAPI設計。主要な変更点ランチャーバージョンにゲームバージョンを対応させるこれまで、ランチャーバージョンにゲームを紐付け、ランチャーに入っているゲームを設定していた。しかし、これでは工大祭とコミケで異なるゲームバージョンを配信したい場合や、過去のコミケで配信したものに機能追加したゲームバージョンを次のコミケでは販売したい場合などに対応できなかった。これをに対応するために、ラ...

実装は、クリーンアーキテクチャベースのアーキテクチャとなっていることを利用して、最初に役割ごとに旧APIの実装を転用しても問題ない箇所、新規の実装が必要な個所を切り分けていきました。具体的には、認証部分やObject Storageとの接続部分については旧APIと果たすべき役割が変わらずほとんど変更を行わずに使えましたが、整合性周りへの対応でドメインのEntity間の関係が変わったことでデータベースとの接続部分や変更が入ったEntityに関するUseCase層は書き直しが必要になりました。また、当然APIの設計が変わっているためAPIの接続部分は完全に書き直しとなりました。体感としては、全体の6割程度が書き直しになった印象です。

また、後述の旧APIから新APIへのダウンタイムほぼゼロでの移行を実現するために、環境変数による簡易的なFeature Flagを導入し、環境変数を変えるだけで新API、旧APIの有効・無効の切り替えができるようにしています。特に旧APIについては書き込みのみの無効化と全面無効化の2段階を用意しています。Feature Flagの実装は、Feature Flagの管理用のpackageで環境変数を読み込み、その結果をAPIで読みこむことで有効・無効の切り替えを行うというシンプルなものです。言葉で聞いてもイメージがわきづらい場合は以下で実装を見ることができます。

trap-collection-server/src/config at 281812f5ddafcd17a05525f1c67fcb6bcf5c220b · traPtitech/trap-collection-server
Contribute to traPtitech/trap-collection-server development by creating an account on GitHub.

そのほかに、データベースのスキーマにも変更が必要となりました。データベースのレコード数がそこまで多くなく、テーブル全てのレコードを再度INSERTしなおしてもそこまで時間がかからないことから、ダウンタイムの削減のために旧APIと新APIが同時に動作できるよう、スキーマの変更ではカラムの削除などの旧APIが動作しなくなる変更が必要となる全てのテーブルを再度作り直すことにしました。

API移行の流れ

コミケではランチャーを販売しており、ダウンタイムが発生しランチャーが正常に動作しない時間が発生するとゲームを遊ぶ機会の損失やランチャーへの信頼性の低下などが発生することが考えられます。また、SysAd班内では数少ないサークル外の人がユーザーのサービスであるため、「外部のユーザーを考慮した移行」を自分がやってみたかったというのもあり、外部ユーザーから見たダウンタイムが極力発生しないことを目指して移行を行いました。ぶっちゃけそこまでユーザー数は多くなくダウンタイムが発生するデメリットは極めて小さいサービスなので、後者の「やってみたかったから」というのが最大の理由となります。

手順としては、以下のようになります。

  1. 旧APIからの書き込みを停止
  2. データベースのマイグレーション
  3. 新API有効化
  4. 新APIに対応したランチャーのリリース
  5. しばらく様子を見て、メトリクスで旧APIへのリクエストが完全になくなったのが確認出来た時点で旧API停止

この手順であれば、マイグレーションに漏れが発生することもなく、ランチャーがAPIサーバーを利用できなくなるのはAPIの有効化・無効化に必要となるサーバープロセスの再起動の間のみとなります。APIサーバーでは起動時に行う特別な処理などはないため、ほぼダウンタイムなしでAPIの移行を実現できました。

まとめ

「外部ユーザーから見える部分で書き込みが発生しない」という特徴を利用して、ダウンタイムほぼなしでAPI移行を実現した事例を解説しました。

今回の移行では「書き込みがない」という特性の有用さを実感しました。移行の楽さ以外にも書き込みがないことにはキャッシュ導入が楽になるなどの多くの利点があるとおもいます。不要な書き込みが発生しない設計を心掛けたいですね。

traPのSysAd班では今回のようにバイトなど以上の自由度のある環境で、バイトなど以上に本格的な開発・運用経験を積むことができます。

また、最初にも述べましたがSysAd班では初心者がWebエンジニアとして必要な知識を身に着けて、本格的に開発・運用の経験を積める環境が整っています。少しでも興味がある方はぜひtraPに入部してみてください。

明日は@dogwood_floの記事です。お楽しみに!

mazrean icon
この記事を書いた人
mazrean

SysAd班で活動したり、百合漫画の布教をしたりしている人。

この記事をシェア

このエントリーをはてなブックマークに追加
共有

関連する記事

2023年4月17日
ポケモンを飼いたい夢を叶える
tqk icon tqk
2023年4月25日
【驚愕】作曲4年目だった男が大学3年間ゲームサウンドに関わった末路...【ゲームサウンドのお仕事について】
tenya icon tenya
2023年3月20日
traPグラフィック班の活動紹介(Ver.2023)
NABE icon NABE
2023年4月27日
Vulkanのデバイスドライバを自作してみた
kegra icon kegra
2023年4月25日
15時間でゲームを作った #Oxygenator
Komichi icon Komichi
2023年3月13日
GoでWebSocketのテスト書く
Ras icon Ras
記事一覧 タグ一覧 Google アナリティクスについて 特定商取引法に基づく表記