デスマTV

https://github.com/hackz-hackathon-ichthyo/Oracle-no-oubou-wo-yurusuna-front

Kotlin

React

Kubernetes

TypeScript

AWS

デスマTVで推しのエンジニアのデスマーチを応援しよう!

notch_man

推しアイデア

エンジニアの開発風景を気軽に公開するための新しい配信サービスを開発しました。GitHubのIssuesで進捗状況が確認できるので、応援メッセージを投げながらみんなで応援しよう!

作った背景

なぜ、デスマーチの配信基盤はないのか?自分の進捗をみんなに応援されたいのはエンジニアの本性のはず!というわけでみんなが釘付けになるちょっとした開発を気軽に公開するためのサービスを作りました。

推し技術

Web RTCの配信基盤を自前で構築しています。reactアプリでは進捗状況やチャットツールを含んだものを提供しています。さらに、ステージング・本番環境を整備しCI/CDも整備して圧倒的開発者体験を実現しました。 Rustも使っていますが一体何が作られたのか???

プロジェクト詳細

プロジェクト詳細

システムの概要

私たちはISUCON11に参加する予定です。 そんな、私たちの唯一の練習環境はcatatsuyさんが公開してくれている社内ISUCONの環境。 しかし、メンバーの1人が宗教上の理由でGo言語を使えないのでRust移植をすることに。 ISUCONは来月、僕らは初心者!こんなところで止まるわけにはいかない! 彼の進捗が心配すぎて夜も眠れない...。だったら、みんなで応援しながらさっさとRust実装を終わらせさせよう! そこで、彼のRust移植を優しく見守るための配信基盤を作ることにしました!

システムの詳細

インフラ

ライブ動画配信基盤

アプリの要となる動画配信基盤にはパブリッククラウドのAWSが提供しているAmazon Interactive Video Service (IVS)を使いました。これを用いることで一対多のライブ配信を実現させています。このサービスを活用することでバックエンドのタスクを削減することができます。Amazon IVSは再生用のSDKが容易されており今回はそれを利用して実行しています。

CDNキャッシュパージの自動化

クライアントの提供にはCDNであるAmazon CloudFrontを用いています。また、CloudFrontのオリジンサーバーとしてAmazon S3を用いています。クライアントをS3にデプロイするたびにCloudFrontのキャッシュを削除する必要がありますが通常操作であるAWSの管理画面からいちいちパージをするのは開発サイクルの高速化にはボトルネックです。今回はAWS LambdaとAWS SDKを用いて自動化させました。S3のオブジェクトが更新されることをキッカケに、対応するCloudFrontのキャッシュ削除をリクエストするように構成しています。

バックエンドの基盤にAmazon EKSを使用

インフラにはAmazon Elastic Kubernetes Service (EKS) というマネージドなKubernetesサービスを用いました。使用きっかけは開発者の技術的興味によるものですが結果的には開発効率の向上に役立ちました。例えばnamespaceの活用により同じクラスター上に複数環境のコンテナをデプロイすることができたことやCDでデプロイした際に即時新しいイメージが適用されることが、開発速度を求められるハッカソンにはピッタリでした。

本番環境とステージング環境の用意

いつもハッカソンでは発表直前に環境を壊してしまうのはよくあることです。本番と全く同じステージング環境を用意して本番が壊れること防止しています。これにより仮にステージングが壊れようともデモで恥をかくことはありません。安心してステージング環境を壊せます!

CI/CDを構成

自動デプロイは最高です。それからフロントのlintチェックも行っています。今回は本番環境とステージング環境を用意しているのでその分だけGitHub Actionsのワークフローを用意しています。mainにプッシュするとステージングにtagでプッシュすると本番環境にデプロイされるようになっています。

以下はインフラ構成図です。

サーバーサイド

サーバーサイドでは以下のAPIを提供しています。

  • GitHub IssuesのStateからタスクの進捗率を計算するAPI
  • WebSocketを介したチャットサーバー

実装はKotlinで行い、Webフレームワークには純kotlin製のKtorを使用しています。 kotlinのwebフレームワークの代表例としてはSpringBootなどが挙げられますが、これらの比べシンプルでGo経験者でも比較的容易に実装できることから本フレームワークを採用しました。

チャットサーバーはパスパラメーターでチャットIDを付与し、同一IDを共有した人たちでブロードキャストが出来るようになっています。今回の実装ではフロントから送られたJSON形式のメッセージをそのままブロードキャストしています。メッセージオブジェクトのスキーマは以下のように定義しています。

{ "id":"example-user-id" // フロントのユーザーを識別するID "text":"hogehoge" // 投稿データ "action":"SEND_MESSAGE" // actionタイプ(SEND_MONEY or SEND_MESSAGE) }

クライアント

フロントアプリはReactで実装しました。以前まではReduxを使った状態管理を行なっていましたが、実装者の思想によりReactHooksを採用しています。 フロントアプリでは以下の機能を提供しています。

  • 配信画面
  • チャット機能
  • 進捗表示機能
  • (配信者専用)認証機能

配信部分のロジックはAWS IVSのライブラリを利用しています。チャットサーバーはブラウザAPIのWebSocketを用いてサーバーと通信を行なっています。テキスト投稿、投げ銭ボタン共にバックエンドのセクションで説明したJSONスキーマに従ってデータを投稿しています!なお、UIフレームワークにはBootstrapを採用しています。

今回、おまけで作った投げ銭機能について説明します。投げ銭機能はボタンを押すとジャラジャラとお金の音が鳴り、お金のアニメーションを動かすものです。アニメーションはCSSで実装しています。クライアントサイドで投げ銭をした時のサウンドと、誰かが投げ銭した時に連動して音が鳴る2つのパターンを用意しています。後者では投げ銭時にチャット基盤を通じてSEND_MONEYのアクションを発火し、アクセス時に生成される自身のランダムID以外の投稿時に音を鳴らすようにしています。こちらの機能は発表当日に突貫で作成したものなので、バグ等があった場合はご容赦ください。

コンテンツ

今回の目が離せないコンテンツは....?

メンターのcatatsuyさんが公開している社内ISUCONのプログラムをRustに移植しました!(オリジナルはこちら: https://github.com/catatsuy/private-isu)

なお、ベンチマーカーですが、Rustの方が低いのはなぜでしょうか?データベースがボトルネックになっている...?

// Rust {"pass":true,"score":9214,"success":8877,"fail":0,"messages":[]} // golang {"pass":true,"score":9414,"success":9075,"fail":0,"messages":[]}

notch_man

@notch_man8600