初めまして。弁護士ドットコム株式会社でエンジニアをやっている@komtaki です。弊社でも開発ブログを開設し、情報発信を強化します。サービス開発事例やデザイン活動を発信するので、お楽しみに。
本記事では、事業とマイクロサービスの視点から、基幹事業の 1 つである弁護士ドットコムサービスの進化を振り返ります。
昨今、クラウドネイティブやマイクロサービスといった概念が普及しました。弊社でもサービスの課題を解決するために、クラウドネイティブを掲げて取り組んでいます。
弁護士ドットコムサービスとは
このサービスでは、一般利用者と弁護士に機能を提供しています。
一般向けには、代表的な 3 つの機能を提供しています。
- 無料で法律相談が投稿でき弁護士の回答がもらえる「みんなの法律相談」
- 検索しいろいろな方法で問い合わせできる「弁護士検索」
- 独自の解釈で切り込む「弁護士ドットコムニュース」
弁護士には、専用ページでユーザーからのお問い合わせを確認する機能、みんなの法律相談に回答する機能、弁護士向けニュースを読む機能が提供されています。
これらの機能を提供することで、悩みを持つ一般利用者を弁護士と結びつけ、問題の解決を目指します。
社名が同じなので少し紛らわしいですが、この記事の弁護士ドットコムサービスとはこの Web サイトを示します。
ビジネスとアーキテクチャの変遷
弁護士ドットコムサービスは、当初はモノリス構造でしたが、サービスの成長と時代の流れに合わせ、マイクロサービスの導入を行ってきました。ただ、その道のりは平坦ではなく、導入してからも試行錯誤を重ねることになりました。
大きく 4 つの時期にわけて、マイクロサービスの導入前から導入後の進化を追いかけます。
1. モノリス期 - EC2
2005 年のサービス開始から 2010 年代まで、赤字だったため事業成長を優先してきました。有効なビジネルモデルを求めて、さまざまな機能を追加、変更、時には廃止。2014 年頃から、今の主要なサービスが出揃いスケールを始めます。
この時期のアーキテクチャは、弁護士ドットコムニュースが Yahoo ニュースに掲載されると大量にアクセスが来るため、それに耐えることを重視していました。Varnish で静的なコンテンツをキャッシュ、モノリスな PHP 5 アプリケーションを EC2 で直接動かし ALB で負荷分散するベーシックな構成でした。
モノリスはピボットしがちなサービス立ち上げ期には向いており、大きな変更がしやすいですが、複雑化しやすい特性があります。
弊社でもサービスがスケールするに従ってシステムが複雑化しました。開発スピードがじわじわと低下、問題になっていました。しかし工数などの理由から、変化に見合ったシステムの抜本的見直しは見送られていました。
ビジネス側でも、サービスが成熟期に入り大きなピボットはもうありません。しかし一般ユーザーから弁護士への問い合わせが伸び悩み、各業界ポータルとの API 連携の話が持ち上がりました。
これらの課題を解決するため、BFF(Backend for Frontend)の水平分割によるマイクロサービスがでてきます。
2. マイクロサービス導入期 - EC2 on Owned Kubernetes
2017 年 4 月に、サービスを分割するプロジェクトが発足し、Gavel というコードネームがつけられました。Gavel(ガベルまたはギャベル)は、裁判や議会などで用いられる儀礼用の小型の木槌の意味です。この小槌でサービスを分割し、API 連携による疎結合とすることで、開発速度の向上を目指します。このプロジェクトは 2018 年 5 月まで続きました。
疎結合化 >> 運用 >> 内部設計
疎結合化が最優先です。工数の観点から、多少の運用負荷増は許容し、言語やフレームワークの変更は見送りました。サービスを分割すれば影響範囲が絞りこめるため、後で改善しやすくなると判断しました。
設計では 3 つのポイントを重視しました。
- どう分けるか
- どう連携するか
- どう運用するか
どう分けるか
サービスをどう分けるかによって、後々のビジネスや開発の方針が大きくかわります。サービス分割により制約ができたとき、ビジネスとサービス境界がズレていると開発速度の低下や開発できない機能が発生します。
これらを避け適切にマイクロサービスの境界を判断するには「集約と境界づけられたコンテキスト」が大切です。
集約と強化づけられたコンテキストは共に、より広いシステムとの適切に定義されたインターフェイスを持つ、ひとまとまりの単位を提供してくれる。集約はシステム内のあるドメイン概念に焦点を当てた自己完結型の状態マシンであり、境界づけられたコンテキストは関連する集約のコレクションを表し、それらはより広い世界への明確なインターフェイスを備えている。
Sam Newman, 2020, モノリスからマイクロサービスへ ――モノリスを進化させる実践移行ガイド ebook版, 第1章4項3段落
弊社でもここを 1 番重視し、境界づけられたコンテキストを定義するため約 600 クラスを分析。これに基づき 1 つの巨大なアプリケーションが、メール、弁護士ドットコムニュース、みんなの法律相談、認証の 4 つの分野の合計 7 つのサービスを切り出されマイクロサービスになりました。それ以外の部分は、本体(フロント)として EC2 に残りました。
どう連携するか
API 連携では、どうやって接続するかも重要です。ここは OpenAPI を使いクライアントを自動生成、社内用の静的 composer サーバーで配布する仕組みを用意。サービスに接続する際には、この composer リポジトリからインストールしたクライアントライブラリを使うよう一元化しました。
どう運用するか
検討を始めた当初、EKS(2017/11/29 発表)はサービス自体なく、ECS も東京リージョンにはありません。GKE はありましたが、センシティブなデータがあるためデータベースを含めすべてを GCP に持っていくのは無理と判断し見送りました。
そうなると自前で Kubernetes をホスティングするしかありません。アプリケーションがシンプルになるよう、インフラに複雑性を隠蔽しました。新設した VPC に kops を使い EC2 上で独自に Kubernetes を構築、構成管理には Helm、サービスメッシュにはLinkerdを採用しました。
大きな知見と新たな課題
CTO が 2017 年 10 月の PHP Conference で「PHP で作るサービスのこれまでの 10 年とこれからの 10 年」と題しこの取り組みを発表しています。
ここからマイクロサービスが始まりました。私はこの時期の最後に入社したのですが「なんてモダンなアーキテクチャ。最先端の技術をキャッチアップしないと」と思ったのを覚えています。
しかし開発していく中で、運用より疎結合を優先した影響が少しずつ顕在化します。問題点は大きく2つありました。
- ビジネス分析が不十分で一部のサービス境界が想定と異なり、開発速度が低下
- インフラ運用コストの増大は想定していたが、想定を超えたコスト増加が発生
差し迫って問題になったのが、インフラです。
- EC2 上に独自に構築しているため3 ヶ月ごとの Kubernetes のバージョンアップ手順が複雑で影響範囲が見えづらく、リスクが非常に高い
- 関連モジュールが多く、バージョンアップの追従が非常に大変
- 本体サービスの PHP 5 の致命的なバージョンの古さによる特殊対応とセキュリティリスク(マイクロサービス側は PHP 7 だったが、本体がコンテナ化しておらず PHP 5 で取り残されていた)
事業会社なので運用のための人的リソースには限りがあり、エンジニアが圧倒的に足りません。さらにエンジニアも異動や退職によって知見が失われています。
運用が完全に崩壊するのは時間の問題です。
サービス境界の見直しも非常に重要ですが、すぐには解決できません。重要度は非常に高いですが、優先度は下げざるを得ません。
3. マネージドマイクロサービス期- AWS ECS
差し迫った状況からインフラの刷新にスコープを絞り、2019 年 10 月に CAU(コンテナ安定運用)プロジェクトが立ち上がります。私を含め多くのエンジニアがアサインされ、より安定したシステム基盤を目指しました。
G(Goal):弁コムのシステム基盤に絡む運用負荷を下げつつサービスを安定させたい T(Target): 弁コムの開発者および運用者は、現在の運用負荷とサービスの不安定さのせいでサービス開発以外の場面で大きなコストを支払っている C(Connect):そこで弁コムのシステム基盤を刷新する
次期基盤候補 EKS vs ECS
次期システム基盤を考えたとき、大きなトレードオフが存在しました。現状に合ったアーキテクチャで ECS を採用し弁護士ドットコムサービス内で閉じるか、それとも将来に向けて EKS を採用して他のサービスにも展開するか。この時点では EKS Fargate などは未発表ですが、EKS はリリースされ、ECS も東京リージョンに来ました。
コンテナオーケストレーションは Kubernetes がデファクトスタンダードになりました。拡張性は高く、資料も多い、ベンダーロックインもされにくい。しかし Kubernetes のマネージドサービスは成熟しておらず、未だバージョンアップ/障害対応などの運用コストが高いです。Kubernetes 専門チームはおらず、インフラのメンテナンスできる人数は限られています。
そしてこのマイクロサービス構成だとコンテナ間通信が少なく、サービスメッシュが不要でした。
これらを踏まえ、現状最適解の ECS に決定しました。もし今後サービスが拡大しても、コンテナ運用と各種バージョンアップにきちんと追従すれば、さらに進化した Kubernetes に戻るのは難しくないでしょう。
ECS への移行
まず Main VPC に取り残された本体のアプリをコンテナ化し PHP 7 系にバージョンアップしました。それと平行でデプロイまわりも作り直し、すべてのサービスを 1 つずつ ECS 上に載せ替えました。VPC をまたぐとネットワークが不安定になるので、DB や Elastic Cache などの AWS リソースも Gavel VPC 側に再構築しました。
4. マイクロサービス整理期
ECS 移行完了後サービスが安定し、サービス境界の見直しの機運が強まりました。先に説明したように、弁護士ドットコムサービスは「弁護士検索」「弁護士ドットコムニュース」「みんなの法律相談」などの機能に分けられるのですが、コンテンツを分類するカテゴリは横断的に使われています。
たとえば「離婚・男女問題」という大カテゴリには「不倫慰謝料」というカテゴリが含まれますが、このカテゴリは 3 つの主要サービスすべてに共通して使われています。不倫慰謝料の記事を見た人が不倫慰謝料の法律相談を見られるように、サービスをまたがって同一のカテゴリを扱えるようになっています。
離婚・男女問題 > 不倫 > 不倫慰謝料
みんなの法律相談サービスの統合
特にこのカテゴリに強く関係しているのが、みんなの法律相談サービスです。「みんなの法律相談」のデータ管理や検索機能、このカテゴリに基づきレコメンドする機能を持っていました。
その結果、本体で表示する際にもカテゴリが必要になり DB に同じスキャンをしたり、複雑になっていました。この開発コストの高さから、みんなの法律相談サービスではなく本体にみんなの法律相談の機能が追加されたりサービス境界が曖昧になっていました。
「弁護士ドットコムニュース」もカテゴリに紐づきますが、上記の不倫慰謝料のページに見つからないはずです。「弁護士ドットコムニュース」は「みんなの法律相談サービス」とターゲットが異なり、ほとんど一見さんで、気になるニュースを見たらすぐ直帰してしまいます。その結果コンテンツが独立しており、カテゴリが弱いのです。
また Gavel プロジェクトでサービスを分割する際「認証サービス」「みんなの法律相談サービス」「弁護士ドットコムニュースサービス」で重複するコードをコピーし、依存関係が複雑化、未使用コードが増えていました。ビジネスロジックが集まっていたコードのコピーは、複雑なアプリのコピーとも言えるでしょう。当然、障害も多発しました。
これらの理由により、2020 年 10 月ごろみんなの法律相談サービスの本体への統合が決定。地道に機能を本体側に再構築しました。また「認証サービス」も依存関係が整理され モジュールコードのコピーは解消されました。
Gavel の時もカテゴリの扱いにおいて議論が紛糾しました。しかしビジネス的な分析をせずに、技術的なコードの分析のみで判断したため見誤りました。サービスの境界を見誤ると、いくら優秀なエンジニアがいてもマイクロサービスは失敗します。
まとめ
サービスを続けていくなかで、ビジネスが変わればアプリも変わります。これからサービスの成長と Kubernetes のマネージドサービスの充実に伴って、ECS から他のインフラに変わる日が来るかもしれません。
弊社のエンジニア・デザイナーの行動指針に「いいものを最短距離で」「最適化し続ける」という 2 つがあります。これからも良いサービスをつくるため改善を続けます。採用をやっているので、チャレンジしたい方の募集を待ってます。
記事を書くにあたって過去資料を見ながら、多くの方にアドバイスをいただきました。
弁護士ドットコムサービスを支えるインフラを知る一助になれれば幸いです。またマイクロサービスで試行錯誤している方の参考になればうれしいです。