Adventar 2019 の技術構成概要

Adventar を支える技術 Advent Calendar 2019 の1日目です。

Adventar はサービスを開始した2012年以来、Rails を利用してサービスを提供してきました。今年はそのシステムを一から設計し直し、以下のような技術要素を使って実装しました。

  • Nuxt.js による SPA なフロントエンド
  • Go で gRPC の API サーバー
  • gRPC-web によるクライアント/サーバー間通信
  • Firebase Authentication による認証
  • envoy で gRPC の proxy
  • AWS Lambda による Nuxt.js の Server Side Rendering
  • Terraform による AWS リソースの管理
  • Serverless Framework による AWS Lambda, API Gateway のデプロイ
  • Amazon ECS, Fargate を利用した API サーバーのホスティング
  • Lambda と CloudWatch Events を利用した定義ジョブ
  • Lambda と API Gateway を使った画像のリサイズサーバー

他にも色々ありますが、概ねこんな感じです。また、今年からソースコードオープンソースにしました。

技術選定について

細かいところは追々説明するとして、今回はなぜこういう技術を選定したのか、について書こうと思います。

実装する前からわかっていたことではあるのですが、これぐらいのサービス(tableは3つ程度、トラフィックも小規模)でこのような構成にするのは完全にオーバーテクノロジーで、私が一人で開発する前提であれば Rails で実装して Heroku でホストするのが実装コストも運用コストも絶対に安く済みます。

今回このようなオーバーテクノロジーな構成を選択したのは完全に個人的な学習目的であり、この規模でこのような構成を選択することはオススメしないということを一番最初に断っておきます。

今回の構成にするのに、最初から今の構成に決めて実装したわけではなく、最初に決めたのは、フロントエンドとサーバーサイドは実装を分けて、次の2つを使うということだけです。

  • gRPC-web
  • サーバーレスな環境(AWS Lambda や Google Cloud Functions)で Server Side Rendering

理由としては、個人的に学びたいと思っているけど直近で利用する機会がなさそうなので、個人サービスで実験的に導入して試してみたいというのが大きいところです。

その他の構成要素はこれらを軸に実装していく上で、比較検討しながら決めていきました。

  • Nuxt.js(フロントエンドのフレームワーク
    • Next.js か Nuxt.js の2択だった
    • Vue.js よりは React のほうが好きだが、フレームワーク的に Nuxt.js のほうがよくできていそうだった
  • Go(gRPC Server)
    • Ruby は仕事でも使っていてお腹いっぱい気味なので別の言語にしたい
    • gRPC サーバーで安定した実装が提供されているのは Go or Java
    • go と Java の知識は同程度(ほぼない)が Go のほうを学びたい
  • ECS/Fargate(API サーバーのホスティング
    • gRPC をホストしないといけないので Heroku は使えない
    • Kubernetes を試してみたい気持ちはあったが自前にしろマネージド(EKS, GKE)にしろ学習コスト、運用コストが高い、マネージドだと料金も高い
    • 適当な VPS や EC2 で systemd とかで運用するというのも考えたが自前でサーバーを管理したくないので多少コストはかかるが ECS, Fargate を選択
  • Firebase Authentication(認証サービス)
    • 対抗は AWS Cognito、Auth0、自前でがんばる
    • 自前はめんどくさいので最後の手段
    • Cognito は要件を満たしてない、Auth0 はお金かかりそう、ということで Firebase Authentication
  • CloudFront(CDN
    • 対抗は Fastly
    • 金額などの面で CloudFront を採用(詳しくは後日)
  • AWS Lambda(FaaS)
    • 色々決めていくうちに AWS によってきたので Google Cloud Functions でなく AWS Lambda にした。あまり比較検討はしていない
  • Serverless Framework(Lambda のデプロイツール)
    • AWS SAM との比較になった
    • ほぼ変わりなかったがプラグインが豊富にありそうだったので選択
  • Terraform(AWS のリソース管理)
    • 特に考える余地なし(対抗は CloudFormation ぐらい?)

だいたいこんな感じです。選定の基準としては

  • 技術的チャレンジの有無
  • 金銭的コスト
  • 時間的コスト(学習コスト、実装コスト、運用コストなどを含む)
  • ユーザー体験

あたりのバランスを考えながら選んでいます。例えば時間とお金が無限にあれば、Kubernetes を使ってみたり、普段利用している AWS でなく GCP をフル活用してみたかったですし、何も技術的チャレンジをしないなら Rails, Heroku が一番コスパがいいのはわかっていました。

細かい話しはもっと色々ありますが、あと24日あるので後に譲ることにします。

明日は Adventar をローカルで起動する方法について書きます。