絶対に知っておきたいマイクロサービスを理解するためのポイントと成功へと導く事例まとめ

合同会社みやびおの大平と申します。私はこれまでの経歴で大規模トラフィックを扱うシステムの開発を数多く経験しており、マイクロサービスを含めシステム開発への知見を蓄積してきました。今回、マイクロサービスというお題をいただき、僭越ながら記事を書かせていただきます。

マイクロサービスについて様々なイメージを持たれていると思いますが、そもそもなぜ企業がこぞってマイクロサービスを導入しようとしているのか、その理由を深く考えてはいないという人も、もしかしたら多いのではないでしょうか。

そこで本記事では何のためにマイクロサービスを導入するのかという基本に立ち返りつつ、成功のために必要な要素や運用上の課題、さらにはその克服の仕方なども含めてご説明します。広範なテーマになるためすべてを網羅的に語ることは難しく、筆者の主観により取り上げる話題に偏りが出てしまうことはご容赦ください。


【目次】

マイクロサービスとは?
1.ビジネス・業務的な側面
2.システムのアーキテクトとしての側面

マイクロサービスのシステム構築で考慮すべきこと
-1.Observability(可観測性)の確保
-2.情報公開
-3.分散システムの課題の克服
-4.Discipline(規律)の崩壊をいかに防ぐか

マイクロサービスの成功・失敗事例
-成功事例:Observabilityの確保と規律づくりが功を奏した
-失敗事例:優れたシステムだけでは成立しないマイクロサービスの難しさ

マイクロサービスを成功させるための心構え

マイクロサービスとは?

マイクロサービスには人それぞれのイメージや定義があり、私自身も確固たる定義を持っているわけではありません。ただ、マイクロサービスという言葉だけが独り歩きすると、話が噛み合わなくなってしまいます。そこで本記事はmicroservice.ioというサイトで紹介されている定義をベースにしたいと思います。こちらは『Microservices Patterns: With examples in Java』という書籍を書かれたChris Richardsonさんによるサイトです。

<What are microservices?>

– Highly maintainable and testable
メンテナンス性とテスト性に優れている
– Loosely coupled
疎結合である
– Independently deployable
独立してデプロイが可能である
– Organized around business capabilities
業務的な能力を軸に整理されている
– Owned by a small team
小さなチームにより所有されている

これらを私なりに解釈すると、以下の2つの側面で見ることができると考えています。

1. ビジネス・業務的な側面

マイクロサービスを導入するケースで多いのは、モノリシックなシステムに多くの機能が実装されている場合です。大きなシステムをエンジニアが一斉に開発しようとしてもスケールしませんし、開発速度も上げられません。一つの機能を追加しようとするとほかの機能にも影響してしまい、コンフリクトが発生しやすくなるためです。デプロイメントパイプラインの調整が必要となるため、デプロイサイクルが遅くなりがちですし、改修箇所の確認や、テストにも時間がかかります。後から開発に参入した人にとっては、システムを把握するための学習コストがかかるという課題も生まれるでしょう。 こういった課題を解決し、開発速度とビジネスのパフォーマンスを向上するためにマイクロサービスが導入されることが多いように思います。

2. システムのアーキテクトとしての側面

もうひとつは、アーキテクトのベストプラクティスとしてのマイクロサービスという側面です。モノリシックなシステムに比べて、適切な粒度で分割したマイクロサービス的なシステムからは開発者ならびに運用者がいくつかの恩恵を得ることができます。ここでは一例として以下の4つの事項について記載します。

リソースの再配置

マイクロサービスではシステムごとに最適なスケーリングとリソース配置が可能です。例えばシステムAがB、C、Dの3つのマイクロサービスに依存しており、Bが最も高頻度で使われるシステムだとしたら、Bに集中してシステムを増強すれば事足ります。

これがモノリシックな構成の場合だと、Bというファンクションの高負荷に引きずられて全てのシステムリソースを増強せざるを得ない、という事態も発生しがちです。

メンテナンス・改修の容易性

大きなシステムの場合は開発言語の変更などはもちろん、ライブラリのバージョンアップだけでもかなりの労力が必要です。また、本来は別の技術で構築したほうが良い機能も、ほかの機能に合わせたスタックで開発することにもなりがちです。

その点、システムが目的ごとに細分化されたマイクロサービスはメンテナンスや作り直しがしやすく、システムごとに最適な技術選択も行えます。

Availability(可用性)の最大化

モノリシックなシステムは特定の機能がダウンするとシステム全体に問題が発生してしまうことがありますが、マイクロサービスの場合は問題のある部分のみを切り離し、サービスを継続することが可能です。

セキュリティの向上

データのIsolationを設定することによって、セキュリティレベルの異なる情報を適切に分離できる事もマイクロサービス導入の動機になると思います。

モノリシックなシステムでデータベースに接続してデータを読み書きする場合は、極端に言うと郵便番号などのパブリックデータに近いデータも秘匿性の高いユーザーの個人データも同じ仕組みで扱ってしまいがちですが、マイクロサービスならデータ保存の仕方やセキュリティポリシー、暗号化の方針などをシステム内で混在させず、明確に分けられます。

マイクロサービスのシステム構築で考慮すべきこと

マイクロサービスの導入を検討する際に必ず押さえておきたいのが、「全てのシステムの課題をマイクロサービスで解決できるわけではない」ということです。例えば小さすぎる組織がマイクロサービスを志すと、少人数で複数のシステムを管理することになるので開発や運用のコストがかさんでしまいます。ある程度の体制や規模が整った組織で導入するのが妥当と言えるでしょう。

そして、マイクロサービスを導入することによって、逆にモノリシックなシステムには無い技術的・組織的な課題を抱えることになるケースも多くあります。得られるメリットを理解しつつも、マイクロサービスでどんな課題に直面することになるのか、あらかじめ考慮した上で導入すべきだと個人的には考えます。

上記を踏まえ、ここではマイクロサービスを構築する際に考慮すべき要素について、私の経験から4つのポイントに絞ってお話しします。

1. Observability(可観測性)の確保

Observabilityは2017年頃からマイクロサービス界隈でよく使われるようになった言葉です。日本語にすると「可観測性」となり、全てのシステムを網羅的に観測し、状況を把握できることを指しています。

大きなモノリシックなシステムの場合は、ログやリソース監視の仕組みがシステム全体で共通していることが多いので、何か問題が起きたときも管理しやすいという利点がありました。それが、複数のマイクロサービスが依存しあって一つのシステムが構築されている場合は大きく状況が変わります。

例えば特定の画面がエラーを起こしたとしたときに依存しているマイクロサービスが5つあったとしたら、全てのサーバーにログインしてログを見るのは非常に骨が折れます。また、システムAの中の一つの機能がB、C、Dのマイクロサービスに依存して構築されていた場合、システムAに問題が発生した際にA自身に問題があったのか、B、C、Dのどこかで障害や遅延が発生したのか、それとも細かいエラーが複合的に積み重なって問題が起きたのか、細かい状況を把握するのも難しくなるでしょう。

そのため、マイクロサービスのようなアーキテクトには状況把握のための専用の仕組みが欠かせません。システムの問題点を把握するには、以下のような値を迅速かつ、多数のシステムを横断して一つのダッシュボードで管理できるような仕組みが必要になります。

・ System Metrics (CPU使用率などシステムの状態を管理)
・ Log Management (アクセスログやアプリケーションログ、エラーログなどを集中管理)
・ Application Performance Monitoring(APM、アプリケーションの実行速度や実行頻度などを管理)


また、マイクロサービスならではの監視・分析の仕組みとしてはDistributing Tracingというツールもよく利用されます。これは複数のAPIを多段で呼び出しているシステムで、一つのリクエスト及びトランザクションでどのAPIにどの程度の処理時間がかかっているかを把握することができるものです。

上記のようなマイクロサービスで求められるObservabilityを向上させるための監視系ツールとして、OSSではPrometheusや Grafana、Zipkinなどがよく使用されています。

商用製品ではDatadogやNewRelicなどが世界的に人気です。Datadogはメトリクスの収集、NewRelicはAPMに強みを持つサービスでしたが、現在はいずれも機能拡張していて、監視すべき値を総合的に管理できるソリューションに成長しています。両社ともNY市場に上場済みで市場からも高い評価を得ていることも、その重要さを測る一つの指標になるかなと思います。

2. 情報公開

API仕様やシステムの仕組みなどについてドキュメントなどをきちんと書き情報公開をすることも、非常に大切です。泥臭い話ではありますが、これは私自身の経験から強く感じる点です。

マイクロサービスによってサービスが細分化されると一つひとつのシステムへのスコープが小さくなり、担当するエンジニアとしては管理がしやすくなります。その一方、適切な情報公開がなされていないと担当者以外の人にとっては裏側でどのような処理が行われているのかがブラックボックス化してしまい、非常に使いにくくなりがちです。

単純にドキュメントが揃っているかどうかだけでなく、一貫した設計のわかりやすさも大事です。例えばインターフェースのAPIの命名規則や振る舞いがマイクロサービスごとに大きく異なったり、名前から想像する処理が行われないような状態になっていると、開発者としては混乱が生じ、開発効率の低下や予期せぬバグを生み出す原因になってしまいます。

仕様がわからないからといちいち人に聞いたり内部のソースコードを読む必要が出てくれば、学習コストも高くなります。結果としてモノリシックなシステムの全体を把握するのと同じかそれ以上の時間がかかることがあります。それではマイクロサービスを志す動機だった「開発速度の向上」が満たせず、システムを分割した意味がありません。

こういった事態を回避するには、以下の例に挙げるような整備をしておくことが必要となります。

APIドキュメントの作成

どのような機能が揃っているのか、渡すパラメーターは何か、どのような処理が行われてどのような結果が返されるのか、どのようなエラーが起こり得るかをドキュメント化する必要があります。

APIのSpecについてはgPRCのようにスキーマドリブンで開発する技術もよく用いられています。Specを決めてから開発を進めることで、開発者と利用者の認識の齟齬が生まれづらくなります。

また、APIドキュメントは、作成の手間を省くために実装に基づいて自動的に生成される仕組みを採用するのも良いでしょう。ドキュメントだけではなく、APIリクエストを送ると仮の値が返ってくるようなHot Mockが自動的に提供されるようなものであれば、なお便利です。技術的にはSwagger/OpenAPIなどを用いることで、比較的簡単にそのような環境を構築することができます。

SDKの公開

マイクロサービスを利用するたびにクライアント実装を書くと実装にムラが出てしまう上に、仕様を誤解してしまうことがあります。マイクロサービスをどのような使い方をしてほしいのか定義するSDKを用意するのが望ましいです。

Statusの公開

あるマイクロサービスに問題が発生していると、そこに依存しているほかのサービスにも影響が出ます。問題の切り分けをより円滑にするためには、マイクロサービスがそもそも正しく稼働しているのかどうか、チームメンバー以外も把握できるようにしておく必要があります。

まず、Statusを判断するためのメトリクスについて、チーム内であらかじめ整理しておくことが必要です。例えばHTTP 500エラーが一定以上発生したら障害、あるいはパフォーマンスがN%低下したら障害にするといった具合です。

それらの値を自動的に取得し、条件に達したらシステムに反映されるような仕組みを用意しておくのがおすすめです。当該のマイクロサービスが障害を起こしたら自動的にCircuit Breaker(過剰に処理要求があったり、エラーが多発した際に接続を遮断する仕組み)のような仕組みを発動させ、安全に切り離すといったことも可能です。

3. 分散システムの課題の克服

マイクロサービスを導入すると、ネットワークを介して疎結合的に接続する分散システム特有の課題を抱えることにもなります。以下のような事項への対処法は考えておくべきでしょう。

トランザクション管理の難しさ

モノリシックなシステム場合は、同じシステム内でのトランザクション管理をDBMSに頼って行うことも可能ですが、複数のマイクロサービスでシステムを構築する場合はそうはいきません。 例えば更新処理を行うAPIを呼び出した際にネットワーク的な問題が発生して接続できなかった場合は、データの不整合が起こりやすくなります。リトライ制御やリコンサイル処理(複数のシステムの状態を突合し、状態のズレが発生しないようにする仕組み)を導入する、冪等性や順序性が大事なデータはKafkaなどのOnline Event Processingのシステムに書き込むアーキテクトにするなど、システム全体の整合性を保つ努力が必要です。

ネットワーク接続の不安定性への対処

ネットワーク接続の処理はメモリ内での処理に比べて複雑で関わる機器も増えるため、一般的に時間がかかりますし、信頼性が低くなります。ネットワークのオーバーヘッドによりモノリシックな構成のときよりパフォーマンスが劣化する可能性もあるため、キャッシュ、データ圧縮化、HTTP/2による通信処理などを有効活用するといった対応が必要です。 また、ネットワークが不通や瞬断、遅延した際に問題が起こらないよう、適切なリトライ処理やTimeout処理を考慮したシステムアーキテクトの検討が必要となります。

障害を極小化するための対応

あるマイクロサービスに障害が発生した際、ほかのサービスに影響が出ないようサービス同士の切り離しが行えるような作りにしておくことも大事です。 上記でも触れたCircuit Breakerのような仕組みを用意すれば、特定のシステムに障害が発生したら代替ページを表示したり処理を切り離すことができます。また、Rete-Limitなどを用いて、特定の処理に過度なトラフィックが流れないようにする仕組みも必要です。

4. Discipline(規律)の崩壊をいかに防ぐか

一般的にはあまり言われていないかもしれませんが、マイクロサービスの開発において、チームの規律の崩壊を防ぐことも非常に大事だと感じています。

マイクロサービスの開発は小さなチームがそれぞれのシステムに裁量を持ち、ライブラリの選定や実装などを自律的に管理することになります。これによって並行開発が行いやすくなるメリットが生まれるのですが、だからと言って各チームがあまりにばらばらな仕組みやレベル感で実装や設計を行ったり、ロギング処理や監視を行うと、システムとしての統制が取れなくなり、カオスが生まれます。 そうなるとシステム全体の品質を保った安全な稼働が実現できないばかりか、チーム間の不信感も広がります。これらの調整が取れないままリリースするとリリース後のリカバリーも難しくなるので、開発体制を作る段階から規律を保つ仕組みづくりをしておく必要があると個人的には考えています。

まず、マイクロサービスであってもログやメトリクスの出し方、デプロイメントパイプラインは組織内で統一をしたほうが無難です。認証処理などコアな部分の共通化も必要です。そしてそれらの規約やルールを組織全体に周知徹底させるために組織横断で動くチームの配置も欠かせません。一般的には、SREや基盤開発を司るチームがこれらの責務にあたることが多いでしょう。

共通化したルールが各マイクロサービスのシステムに適切に適用されているかどうかをチェックする体制も重要です。開発やサービスリリースのプロセスの中に、レビュープロセスを含んでおきましょう。チームでセルフチェックするのであれば、Production Readiness Checklistなどを用意して、抜け漏れがないかを確認することも有効です。また、組織横断的なアーキテクチャレビューや各システムの説明会を行うような取り組み、場作りも円滑な開発と組織運営において役立つと思います。

その他、マイクロサービス導入で開発組織が直面する課題への具体的対応については、『Production Ready Microservices』という書籍が非常に実践的で参考になると思います。私も多くの要素を本書から参考にさせていただいています。

最後にリーダーシップについて。マイクロサービスはシステム全体としては大きな構成になることが多いため、全体像の把握は当然大変です。場合によっては、モノリシックなシステムよりも手間がかかることもあるでしょう。しかし、システム全体を把握している人でなければ判断できないことがありますし、細かいチームだらけになると、全体に問題があったときに誰もリーダーシップを取らないという事態が起こり得ます。

そのため、マイクロサービスのシステムにおいてもビジネス的・技術的に全体を俯瞰して意思決定をする立場の人が必要です。その人が的確な判断をするためにも、各マイクロサービスの適切な情報公開が大切になるというわけなのです。

組織がサイロ化して自分の関わるサービスにしか興味が持てなくなるような状況を回避し、メンバー全員が健全に「コト」に対処できるような組織と文化、雰囲気づくりが、マイクロサービスに適合した組織を作り上げるためには大事な要素だと、個人的には考えています。

マイクロサービスの成功・失敗事例

ここまでご説明してきましたが、私自身も上記に述べたようなマイクロサービスに求められる要件を全て満たすことができた事例は正直ありません。何がが成功か失敗かというジャッジは難しいですが、個人的な観点で、部分的に満たしていて成功したと感じられた事例、そして一部を満たせずに失敗したと感じた事例をそれぞれ1つずつご紹介します。

成功事例:Observabilityの確保と規律づくりが功を奏した

一つは、ある大規模なECサイトのシステムの一部をマイクロサービス化した事例です。

サイトは巨大なモノリシックなシステムで、セール時など突発的な負荷に対して適切にスケーリングができずにいたことが課題でした。そこで、コアな処理部分を疎結合なシステムとして分離し、負荷が増えた場合はその部分だけ集中的にスケーリングすることで、効率的なリソース配置ができる構成にしようとマイクロサービスを導入しました。技術的にはそこまで先進的な攻めた構成、技術的に面白い構成は取らず、ベーシックな仕組みで対応をしました。

導入にあたって特に気を使ったのが、Observabilityの確保や規律づくりです。ObservabilityについてはDatadogやNewRelic、Sentryといった仕組みを組み合わせ、分散環境でも適切にシステムの状況が把握できる環境を用意しました。 また、システムについては必ずメトリクスベースで意思決定ができるようにして、アラートの通知ルールや障害時のオンコールの対応についても整備しました。段階的にリリースすることで、開発者や運用担当者の習熟度を段階的に引き上げる取り組みも行っています。

システム内容について、チームはもちろん組織全体に共有する時間も多く確保したのもポイントです。チーム内での日々の情報共有や、スキルレベルを一定水準に保つためのハンズオン的な活動も頻繁に行いました。

これらの取り組みによって、アーキテクトの変更や新しい概念のシステム導入によって起こりがちな組織の混乱は緩和でき、システムとしても当初の目的を最低限達成できたプロジェクトとなりました。

失敗事例:優れたシステムだけでは成立しないマイクロサービスの難しさ

もう一つは、技術的にはよく出来ていたものの組織として課題が非常に多いと感じた事例でした。

マイクロサービスを導入はしたものの組織として規律が保たれておらず、マイクロサービスごとの質に大きな優劣が生まれてしまっていたのが大きな問題点です。マイクロサービスA、Bの進捗を聞くと両者の担当者は90%と答えるものの実際はAが90%、Bが10~20%程度しか完成しておらず、サービスを安定稼働できない状態がありました。ドキュメントや開発プロセスも整備されていなかったため、前日に合意を取ったはずの仕様が翌日には変更されて、システムが突然動かなくなってしまったことすらありました。全体的に、コミュニケーション不全が発生していたと感じています。

実際のところ、これらの課題はごく一部の優秀なエンジニアが超人的な力を発揮して解決し、サービスは無事リリースに至りました。しかし他のメンバーは置いてきぼりになるという状況が慢性化し、開発メンバーには不満や不安が大きく募る結果となってしまいました。システムは洗練されたマイクロサービスでしたが、組織としてはモノリシックでスケーリングが難しい状態だったと感じています。

システムを上手く構築できたとしても、組織が対応しきれなければマイクロサービスは上手くいきません。それどころか、組織としてデメリットが大きく露見してしまうこともあると感じています。

マイクロサービスを成功させるための心構え

本記事でご説明した通り、マイクロサービスがすべてを解決するということはなく、メリット・デメリットを正しく理解して、適材適所で適材適所で取り組むことが大切だと感じています。一例として、規模が小さすぎる組織でマイクロサービスを導入してもメリットはあまりないことが多く、一定規模以上の企業が迅速にユーザーに価値を届けようと思ったときに、マイクロサービス的な考え方や技術が必要になると思います。また、マイクロサービス導入により遭遇する課題についてもできる限り認識をし、組織として解決できるような体制づくりも大事になると思います。

最後に、よく言われることだとは思いますが、マイクロサービスは手段であり目的ではありません。開発に関わるものとして、システムやサービスを通じてユーザーに価値を届けることが一番大事であり、なおかつ開発者たちも疲弊せず楽しく開発できることが理想の状態であり、目指すべきゴールだと思います。マイクロサービスなどのトレンドワードが世の中に現れるとついつい表層的にキャッチアップしがちで、そのこと自体は悪いことでは無いと思います。ただ、何を達成するために導入するのか、そのゴールについてはブレずに見据えていくことが大事だと思います。

プロフィール:

合同会社みやびお 代表社員 大平哲也
B2C系の大規模サービスを提供する各社でサーバーサイドエンジニア、SRE、エンジニアリングマネージャーなどを努めた後、現在は某社でサーバーサイドエンジニアとして勤務しつつ、空いた時間で副業として案件の開発支援やコンサルティングなどを行っている。 さだまさしのコンサートが心の拠り所だが、コロナ禍によるコンサート延期が続き深刻なさだロスに陥っている。



この記事を書いた人
FLEXY編集部
FLEXY編集部
ハイスキルIT人材への案件紹介サービス
FLEXYメディアは、テックメディアとしてテクノロジーの推進に役立つコンテンツを提供しています。FLEXYメディアを運営するのは、ITに関連するプロシェアリングサービスを提供するFLEXY。経営課題をITで解決するためのCTOや技術顧問のご紹介、ハイスペックエンジニアやクリエイターと企業をマッチングしています。【FLEXYのサービス詳細】求人を募集している法人様向け/お仕事をしたいご登録希望の個人様向け

週1日~/リモートの案件に興味はありませんか?

週1日~/リモートの関わり方で、「開発案件」や「企業のIT化や設計のアドバザリーなどの技術顧問案件」を受けてみませんか?副業をしたい、独立して個人で仕事を受けたエンジニア・デザイナー・PM・技術顧問の皆様のお仕事探し支援サービスがあります。

FLEXYでご案内できる業務委託案件

業務委託契約・開発案件(JavaScriptメイン)

テーマ FLEXY登録画面から案件詳細の確認と直接応募が可能です
勤務日数 2-3日/週
報酬 4万円/日
必要スキル JavaScript・React
勤務地 東京都内/リモート含む
リモート

外部CTO、技術顧問

テーマ 技術アドバイザリーとして知見と経験を生かす
勤務日数 1日/週
報酬 10万円/日
必要スキル エンジニア組織立ち上げや統括のご経験、コードレビュー経験、技術的なアドバイスが出来る方
勤務地 東京
リモート 相談可

業務委託契約・インフラエンジニア

テーマ FLEXY登録画面から案件詳細の確認と直接応募が可能です
勤務日数 2-3日/週
報酬 5万円/日
必要スキル それぞれの案件により異なります
勤務地 東京
リモート 相談可

業務委託・フロントエンドエンジニア

テーマ FLEXY登録画面から案件詳細の確認と直接応募が可能です
勤務日数 週1日〜
報酬 5万/日
必要スキル それぞれの案件により異なります
勤務地 東京
リモート リモートと常駐のMIXなど

人材紹介のCTO案件(非公開求人)

テーマ CTO、技術顧問案件はFLEXYに登録後、案件をコンサルタントからご紹介します
勤務日数 業務委託から人材紹介への移行
報酬 年収800万以上
必要スキル CTOとして活躍可能な方、エンジニア組織のマネージメント経験
勤務地 東京
リモート 最初は業務委託契約で週3日などご要望に合わせます

業務委託契約・サーバサイドエンジニア

テーマ FLEXY登録画面から案件詳細の確認と直接応募が可能です
勤務日数 週2-3日
報酬 案件により異なります
必要スキル 案件により異なります
勤務地 東京都内
リモート 相談可能
個人登録

お仕事をお探しの方(無料登録)
法人の方(IT課題の相談)