見出し画像

GoとgRPCを用いたサービスベースアーキテクチャへの移行

導入

こんにちは。ワンキャリアでバックエンドエンジニアをしている田中(@kakke18_perry)です。業務では、ONE CAREER CLOUDの開発に携わっており、リアーキテクチャの一環で、一部の機能をGo+gRPCでリプレイスしています。

本記事では、そのリプレイスにおけるアーキテクチャや技術の選定理由と振り返りについてお話します。



背景

現在のワンキャリアではプロダクトごとのモノリシックなアーキテクチャを採用しており、メインとしてRuby on RailsとVue、AWSを使用しています。社内にもナレッジが多く、優れたフレームワークであることから、開発生産性の向上に大きく寄与してきました。

一方で、複数プロダクトを開発運用する中で「認知負荷の増大」という課題が顕在化しつつあります。ONE CAREERはリリースから9年、ONE CAREER CLOUDはリリースから3年経過しており、すべての仕様を把握することが困難となっています。開発アイテムによってはONE CAREERとONE CAREER CLOUDの両方に実装が必要となり、開発者はリポジトリやチームを跨いで開発しなければなりません。

そのような中で、あるドメインに関するコードを移行するチャンスが来ました。この移行のためだけでなく、今後のワンキャリアの開発のためにも「サービスベースアーキテクチャ」と「Go」と「gRPC」を用いて今回の移行を行なうことに決定しました。ワンキャリア内の技術選定は基本的にチームメンバーからの発信で、その意思決定が未来の開発効率を大きく阻害するものでなければ、承認される文化があることも後押しとなりました。


選定したアーキテクチャ

書籍「ソフトウェアアーキテクチャの基礎」では、モノリシックアーキテクチャと分散アーキテクチャについて以下のような説明がされています。

アーキテクチャスタイルは、モノリシック(すべてのコードが単一のデプロイメントユニットで構成されている)と分散型(リモートアクセスプロトコルを介して接続された複数のデプロイメントユニットで構成されている)の2種類に分類できる。
(中略)
分散アーキテクチャは、パフォーマンス、スケーラビリティ、可用性の点でモノリシックアーキテクチャよりもはるかに強力だ。しかし、そのパワーには大きなトレードオフがある。 

背景で述べたような認知負荷の増大に対処すべく、今回選んだアーキテクチャは、分散型の中のサービスベースアーキテクチャです。
本書では、サービスベースアーキテクチャについて以下のような説明がされています。

サービスベースアーキテクチャは、分散型のマクロなレイヤード構造を取り、個別にデプロイされたユーザーインターフェイス、個別にデプロイされた粒度の粗いリモートサービス、そしてモノリシックなデータベースから編成される。

参考書籍はこちら


私たちがサービスベースアーキテクチャを選定した理由は以下の2点です。

  • ONE CAREER CLOUD以外のプロダクトと共通のデータベースを使っているため依存度がかなり高く、DBを含めて分散型にするのはリスクもある上に、工数もかかるから

  • 分散型のアーキテクチャスタイルを選択することで認知負荷が本当に下がるのか懸念があり、ミニマムで始めたかったから


選定した技術

次に選定した技術についてお話します。選定した技術は以下の通りです。

  • サーバ:Go

  • フロント:Vue

  • インフラ:AWS(ECS)

  • サーバフロント間の通信: gRPC Web、gRPC Web Proxy(Envoy)

今回は0からサービスを開発するわけではなく、既に動いているONE CAREER CLOUDに組み込むという形だったので、フロントとインフラに関しては既存の技術を選択しました。マイクロフロントエンドやマルチクラウドという手段もありますが、今回の主題ではないため見送りました。


Goを選択した理由

Goを選択した理由は以下の通りです。

  • 静的型付け言語だから

  • 言語機能がシンプルなため、書き手による差異が少なく、可読性が高いから

  • 筆者が好きだから

他の候補としては、Rustがありました。ワンキャリアにはRustのコントリビューターがいるので候補として挙がりましたが、当時はGoを書ける人が多かったためGoが選択されました。今考えると、TypeScriptなども選択肢として挙げることができたら良かったのではないかと思います。

筆者がGoを好きな理由は、Goを選択した理由の2つ目にあげた「言語機能がシンプルなため、書き手による差異が少なく、可読性が高い」からです。ソフトウェアを開発するときにはコードを書くことより読むことの方が圧倒的に多いので、可読性はとても重要視しています。もちろんGoを選択するだけで可読性が上がるわけではないので、package構成や静的解析ツールについては後日別のテックブログでお話しようと思います。


gRPCを選択した理由

gRPCを選択した理由は以下の通りです。

  • 今後、ワンキャリア内で分散型アーキテクチャが広まった時に、デファクトスタンダードであるgRPCの知見が欲しかったから

他の候補としては、GraphQLやOpenAPIがありました。今回のサービスベースアーキテクチャへの移行のみを考えるならば、これらの選択肢の方がメリットが大きいと思いますが、将来的なことも考えた上でチャレンジングな試みとしてgRPCを選択しました。

gRPCを採用する中で考慮しなければならないポイントは、「ブラウザから使うにはプロキシが必要」ということでした。当時Connectという選択肢を持っていなかったので、必然的にgRPC Webを使うことにしました。プロキシの準備などデメリットがありましたが、今回はチャレンジということで許容しました。


リリースから2ヶ月後の感想

選択したアーキテクチャと技術について、開発中からリリースから2か月後までを振り返ります。

開発中

gRPCを選択したことでスキーマ駆動開発となり、実装の初期段階からAPIを使う側・使われる側の視点で実装、レビューを進めることができました。また、普段はRuby on Railsで実装している開発者からは「Goには型があり、静的解析ツールも充実してるので、開発速度と保守性のバランスが良い」という感想もいただきました。

一方で、「Ruby on Railsの方が開発速度は速い」という感想もありました。また、gRPCは、シリアライズにProtocol Buffersという技術を使用しているので、ブラウザの開発者ツールでサーバからのレスポンスを閲覧できないという問題もありました。こちらに関しては、デバッグログを仕込むことで一定のペインは解消されました。

リリース〜リリース後2ヶ月

サービスベースアーキテクチャに移行したことで、そのドメインに関する質問や相談が自然と筆者のチームに集まるようになりました。これにより開発者は、仕様やコードだけでなく、顧客の業務フローについても理解が深まり、認知負荷を減少させただけではなく、よりユーザーファーストにプロダクト開発を進めることができると感じています。

しかし、プロキシサーバをgRPCサーバとは別で用意しているため、エラー発生時に切り分けが困難というデメリットもあります。こちらについてはConnectに移行したりBFFを導入したりするなど、もう少し中長期的に考える必要があると感じています。


まとめ

リアーキテクチャの一環で、GoとgRPCによるサービスベースアーキテクチャへの移行を行いました。現時点でもメリットとデメリットの両方を感じられ、良い収穫になったと思います。今後全社的にサービスベースアーキテクチャへ移行していくのかについては議論が必要ですが、ミッションの実現やプロダクトの成長において何が最善かを模索していきたいと考えています。

ワンキャリアのエンジニアは、コアバリューである「本質的・長期的思考」をもとに、こうした将来を見据えた技術的なチャレンジを行なっています。少しでもご興味を持っていただけた方は、ぜひご連絡ください!


▼ワンキャリアのエンジニア組織のことを知りたい方はまずこちら

▼カジュアル面談を希望の方はこちら

▼エンジニア求人票


この記事が参加している募集

オープン社内報

この記事が気に入ったらサポートをしてみませんか?