こんにちは!株式会社ハイヤールー代表葛岡(@kkosukeee)です。
優秀なエンジニア採用に必須のコーディング試験サービス『HireRoo(ハイヤールー)』で使用している技術を紹介すべく、HireRooテックブログをはじめました。
記念すべき第一弾の記事は我々のサービスがどの様な基盤でどのように動いてるかを俯瞰で紹介していきます。
今後記事をいくつかに分け、コアな部分がどのように設計・運用されているかも紹介していきますので是非ご一読下さい!
サービス基盤
まずはじめにHireRooがどの様な基盤で運用されているのかを紹介します。
HireRooはマイクロサービスアーキテクチャでGCPのCloud Run上にデプロイされています。サービス間の接続にはgRPCを使用し、リソースの管理にはTerraformを使用しています。
Terraformによるテンプレート化
マイクロサービスではいくつものサービスが共に会話しユーザーからのリクエストに応答します。これらのサービスには重複部分があり、新しいサービスを作成する度に重複部分を実装するのは非効率的です。そこでシステムの基盤部分をTerraformでテンプレート化しておくことで、各サービスの開発効率を上げることができます。
TerraformはCircleCI上でGCPにApplyしています。共通化されたテンプレートに各サービスで使用するDocker imageや必要なメモリなどを記述しセントラルレポジトリにPushすることでCIがトリガーされ(図2)、クラウドリソースがGCP Projectにデプロイされていきます(図5)。
続いてこのようにデプロイされた各サービスがどのように互いに会話しているかを見ていきます。
インターフェイスドリブンなサービス間通信
前述の通り、マイクロサービスではいくつものサービスが互いに会話することでリクエストに応答します。各サービスがそれぞれインターフェイスを提供しそのインターフェイスに準拠し各サービスは会話します。
直接違うサービスのDBに書き込みするなどはアンチパターンであり、DBに書き込みしたい場合でもサービスが提供しているインターフェイスに準拠し、RESTやSOAPなどで会話することが好まれております。(マイクロサービスアーキテクチャの概要)
私達はProtocol BufferをIDL (Interface Definition Language) として、gRPCを使用しサービス間での通信を行っています。Terraform同様セントラルレポジトリにInterfaceを記述したprotoファイルを集約させ、CI上で各言語のクライアントライブラリを生成しています(図3.1)。
こうして定義されたインターフェイスをもとに自動で生成されたクライアントライブラリを各サービスで使用しサービス間の通信を行っています。
続いてサービス構成を紹介します。
サービス構成
HireRooは現在ウェブアプリケーションのみ提供しており、Typescriptで書かれたReactのSPA (Single Page Application) をFirebase Hosting上にデプロイしており(図1)、Goで書かれた各マイクロサービスのバックエンドサーバーとCloud EndpointsによりデプロイされたEnvoy Gatewayを介して通信(図2)しています。
ユーザーの認証にはFirebase Authenticationを使用しており、Cloud EndpointsによってデプロイされたEnvoyのGatewayが全てのリクエストの認証情報を確認しバックエンドサーバーに流しています(図3)。
続いてフロントエンドとバックエンドの構成をもう少し詳しくみていきます。
フロントエンド
前述の通りフロントエンドはTypescriptで書かれたReactのアプリケーションとなっています。UIフレームワークはMaterial UIを採用しており、Atomic Designを実現しています。
フロントエンドとバックエンドの通信にはgrpc-web(図2)を使用しているため、全てのリクエストとレスポンスは型が定義されており、デグレなどが発生した場合ビルドがコケるため安定したアプリの継続的なデリバリーが実現できます。
grpc-webを導入するまでは事前に全てのリクエストとレスポンスの型を定義、もしくは any
を乱用していたため挙動が不安定でしたがgrpc-webを導入することでクライアントのコードが減るだけでなくより安定したアプリケーションを開発することができました。
バックエンド
バックエンドのサーバーはCloud Run上でサーバーレスアプリケーションとして走っており、各サービスは一部機械学習を使用するサービスを除きGoで実装されています。
サービスは二階層構造で構成されており、コアサービスの層とコアをラップするBFF層に別れています。コアなサービスに関しては別記事で紹介しますが、アルゴリズムの問題をクラウドでコンパイルでき定量評価できる『Challenge』サービスや、β版では制限中のAIやバックエンドなど技術特化型の問題を解く『Project』サービスなどが存在します。
HireRooにはSpot選考とBatch選考という機能が現在存在しており導入企業様に使っていただいております。(Spot選考とBatch選考の紹介は別記事を御覧ください)
Spot選考とBatch選考をクライアントアプリケーションに露出するサービスとして『Spot』サービスと『Batch』サービスが存在しており、共にコアである『Challenge』と『Project』にアクセスするためのインターフェイスを担っており、クライアントはBFFである『Spot』と『Batch』サービス経由でコアデータにアクセスしています(図4)。
コアサービス層に関しては別記事で詳細を紹介するため割愛させていただきますが、以上がHireRooのサービス構成の俯瞰説明となっています。まとめると以下のような図になります。
技術の選定理由
HireRooは非常にモダンなシステム設計となっています。その一方読者の中にはスタートアップがいきなりマイクロサービスでシステムを構築するのに懐疑的な方や、RESTが主流なのにgRPCを選んだ理由など気になる方がいるかもしれません。
ここではそれぞれの技術をどの様な基準で採用したかを簡単に触れたいと思います。
マイクロサービス vs モノリス
仮説検証段階ではプロダクトは日に日に形が変わります。新しくデプロイした新機能が数週間後には全く違う形としてプロダクションで動いてるということはよくあります。現に初期段階ではATSとしてのサービス『Flow』機能を開発しておりましたが、リリースから数週間でクローズしたことがあります。
モノリスのシステムを運用するとこのような場合『Flow』という機能を殺すためにもデグレが発生していないか、データの整合性はとれているか、Flowドメインは消えるがリレーションは正しく設計されているかなど考えることが必要以上に増えます。
マイクロサービスアーキテクチャではこの様な変更がある場合、別のサービスは全く触れず、対象のサービスの導線を隠すことで機能のクローズやリリースが容易になります。他のサービスと疎結合のためデグレの心配やデータの整合性を考える必要はなく、迅速にプロダクトの変化に対応できます。
その一方マイクロサービスは基盤部分への投資などが必要なため一概に誰でも導入すべきものではありません。幸いにも前職のメルカリがマイクロサービス on K8sで有名だったり、ある程度ノウハウがあったので最終的にマイクロサービスの採用に至りました。
gRPC vs REST
マイクロサービスではシステム同士での会話が必然的に発生します。これはモノリス構造だとそこまで発生しませんが、マイクロサービスでは1つのサービスにクライアントが要求しているデータがすべて格納されていることはありません。
gRPCを採用した大きな理由としてIDLであるProtocol Bufferの存在があります。RESTではSwaggerだったりインターフェイスドリブンな開発は主流になっております。Protocol Bufferでは各言語のコンパイラーを使用しクライアントライブラリを自動で生成できたり、多くのメリットがあります。
前述したとおり、フロントエンドとバックエンドの通信にもgRPCを使用しているため、単一のインターフェイスから複数の言語のクライアントライブラリが自動で生成できるのは非常に魅力的であり、かつインターフェイスで会話するマイクロサービスではgRPCが圧倒的にRESTより魅力的だと判断したためgRPCを採用しました。
その一方RESTがほとんどのサービスで主流なため、ブラウザが対応していなかったりgrpc gatewayのようなProxyを立てないとgRPC完結のシステムが構築できないといったデメリットもあります。幸いにも私達はRESTからgrpcに変換してくれたりgrpc-webに対応しているProxyであるEnvoyをGatewayとしてCloud Endpointsで管理しています。これによりデメリットをあまり感じられなかったのでgRPCの採用に至りました。
さいごに
ここまで読んでいただきありがとうございました。HireRooは非常にモダンな技術の寄せ集めで設計されています。これらの技術を通しコーディング試験を支えるクラウドでのコンパイルやコードの自動評価、オンラインIDEなど様々な機能を実現しています。
HireRooではこれらのモダンな技術を使用し一緒にプロダクト開発ができるエンジニアを絶賛募集中です。誰もが知る大規模サービスの設計・開発経験のある粒ぞろいのエンジニアやと一緒に開発してみませんか?もし少しでも興味を持っていただけたのであれば、是非お気軽に以下採用フォームからお問い合わせ下さい!
今後も日本にコーディング試験を普及し、エンジニア採用の新しい当たり前を実現すべくHireRooの開発と情報発信を技術ブログを通して行います。それではまた!