技術とアーキテクチャ
最終更新
最終更新
この図は、Wantedly というサービスの向かっているソフトウェア構造を大きなレベルで抽出し(アーキテクチャ)、それぞれの部分でどのような技術を使っているのかを重ねたものです。この章では、この図を元にして Wantedly のアーキテクチャと技術について概観します。
Wantedly のサービスは、各々が独自のリリース・サイクルを持つ多数のソフトウェア・コンポーネントの組み合わせによって動いています。
例えば、iOS というプラットフォームにおいて提供している Wantedly Visit アプリは、App Store に申請を行い、申請が通ってリリースされることでユーザーの目に見える改善・機能追加となります。同様に、Web というプラットフォームにおいても、React を使ったアプリが(多くの場合は iOS よりも短いリリース・サイクルで)改善されていきます。
このように多数のアプリが異なるプラットフォームで提供されているため、コンポーネントの数としては一桁オーダーで存在します。
ほとんどのアプリは、「募集」や「プロフィール」などのデータを扱うため、バックエンドのシステムを必要とします。現在、多くの箇所ではバックエンドとは API を通じてやり取りしています。
バックエンドのシステムはバックエンドのシステムで、多数の個別にリリース可能なソフトウェア・コンポーネントからなっています。ただし、積極的にドメインを分けることを目的としているわけではなく、必要に応じて分化することができる進化的なアーキテクチャを採っています。コンポーネント数としては二桁オーダーで存在します。
アプリおよびシステムからは様々なデータが生まれます。これらのデータは、BigQuery というデータウェアハウスに一元的に集約していて、サービスの推薦機能や改善のための意思決定に使われています。実際のところ、このレイヤーは単なるデータの置き場所ではなく、我々の立てた Kubernetes クラスター上のシステムではなかなか扱いづらい大規模なデータの分散処理基盤としても大いに活用しています。
アプリを記述するプログラミング言語は、それぞれ TypeScript、Swift、Kotlin を採用しています。Wantedy のサービスが開始した時点では、各プラットフォーム上のプログラミング言語は JavaScript、Objective-C、Java でした。これらはどれも80年代-90年代に設計されたプログラミング言語であり、よく設計されてはいますが積み重なった課題も多く、アプリのリニューアルなどのタイミングで積極的なリライトを行なっています。
プログラミング言語以外では、Web における UI 構築のために2016年から React を導入しています。それまでは Ruby on Rails の Haml によるサーバーサイドレンダリングでしたが、優れた UI/UX を実現するためにクライアントサイドにおけるレンダリングに切り替えています。
このような抽象化技術の導入は、2017年に Wantedly Design System を定義してから、デザインシステムライブラリの構築などにも役立っています。Wantedly Design System は、異なるプラットフォームで提供する場合のデザインの重複をなくすと同時に、サービスを利用するユーザーには共通の UI/UX を提供することを意図しています。
また表層から離れると、モバイルアプリの iOS と Android におけるビジネスロジックの共通化を行う技術として、Kotlin Multiplatform Mobile (KMM) を導入しています。
Wantedly のサーバーは全て Docker コンテナの中で動作し、Kubernetes というコンテナオーケストレーションの基盤の上で動いています。これらはマイクロサービスの単位で独立してテスト・デプロイされます。
Docker や Kubernetes のような抽象化技術を導入しているため、マイクロサービスの実装に複数のプログラミング言語を使う選択肢が採れます。Wantedly で現在サーバーの実装に使われる主要な実装言語は Ruby, Go, Python です。マイナーなものとしては TypeScript、Rust があります。
Ruby は一番最初から使用していた言語で、サービスに必要な機能を一通り高速に実装し、改善していく用途で今も多くの箇所で使用しています。主要なドメインのデータは Rails のサーバーに置くことがほとんどです。
Go は開発のリードタイムよりも安定性やスケーラビリティが求められ、責務が明確なマイクロサービスの実装に使用しています。1プロセスが軽量であったり、並行処理の機構が充実しているのも、Kubernetes 上で動かすマイクロサービスの実装と相性が良いです。
Python は機械学習・推薦を行うマイクロサービスやバッチジョブで使用しています。例えば、Wantedly People の名刺を取り込む際には、「文字列のカテゴリーを当てる」「読み仮名を推定する」などのタスクをそれぞれマイクロサービスで処理しています。
こういった異なる技術で実装されたコンポーネントを上手く協調して動かすためには API がとても重要になります。そのために、Protocol Buffers という実装と紐づいたスキーマ記述言語を使用しています。
Protocol Buffers はシリアライゼーション・フォーマットでもあり、そのデータは任意の方法で送ることができます。Wantedly の場合、gRPC で同期的にやりとりを行うか、メッセージング・サービスである Google Cloud Pub/Sub で非同期的にやりとりを行うかの二つの手段を用意しています。マイクロサービス・アーキテクチャのような分散システムにおいては、全てを同期的にやりとりしてしまうと強い依存関係が生じてしまうため、非同期メッセージングが適した箇所では Pub/Sub も利用しています。
システム内部の通信は以上の手段を推奨していますが、アプリから呼び出す際には、GraphQL の gateway サーバーを叩きます。GraphQL は我々が提供したい各アプリ・プラットフォームにおいてエコシステムがあること、そして UI にどこまでの情報を表示するかによって API が返す情報量がしばしば変わるという、普遍的な要件に対して解決をしていることから採用しています。ただし、API にスキーマを与えることは Protocol Buffers で解決しているため、この gateway サーバーは Protocol Buffers から半自動生成した薄いものとなっています。
最後に、さまざまな技術に触れましたが、これら全てが同時に必要になることはないので、安心してください。ここでは、Wantedly で利用している技術とそのつながりのインデックスを作ってもらうことで、Wantedly Engineering Handbook を歩きやすくすることを意図しています。
Slack: #engineering
Wantedly の技術とアーキテクチャの変遷 (internal)
主要なアーキテクチャ課題と解決指針 (internal)