blog

[microservices]
Microservices 入門 #01

この記事は foodison advent calendar 2015 の14日目の記事です。

こんにちは。 エンジニアの市川です。 熱しやすく冷めやすいです。

はじめに

今回は swagger の記事は一休みさせてもらいまして、Microservices について書かせてもらいます。 というのも、先週 API Meetup Tokyo #11 というイベントに参加させていただきまして。 その回で Microservices ( マイクロサービス ) がフィーチャーされており、備忘録がてら書かせてもらおうという感じでございます。 … たぶん長くなるので、3 回連載くらいになるかと 汗

初回では、Microservices の概要や特徴について書かせてもらいます。

Microservices ( マイクロサービス ) とは

ソフトフェア開発のアーキテクチャで、ひとつのアプリケーションを、複数の軽量なサービスを連携させて開発しようというアプローチです。 サービス間の通信には RESTful Web API や軽量のメッセージングを利用し、各サービスは独立してデプロイ、動作が可能。 また、各サービス毎に最適なプログラミング言語やデータストレージを選択し、利用します。

マイクロサービスの対義語として、Monolythic ( モノリシック:一枚岩) という言葉がよく使われます。 例えば Ruby on Rails で開発されるようなアプリケーションの大半は、1つのサービスの中にさまざまな機能が盛り込まれています。 ユーザ管理、認証、課金、メッセージ配信 … 。 内部はオブジェクト指向等でモジュール化されてはいますが、サービス自体はたくさんの機能を含んで1つにまとまっています。

Microservices ( マイクロサービス ) という言葉は James Lewis 氏が 2012 年に発表した Microservices - Java, the Unix Way が起源とされており、その後 2014 年に James Lewis 氏が Martin Fowler 氏と執筆した Microservices により、注目を集めるようになりました。 日本語訳もされているので、お時間のある方はご一読されると、より理解が深まるかと思います。

Microservices の特徴

ここからは 9 つある、マイクロサービスの特徴を見ていきましょう。

サービスによるコンポーネント化

  • コンポーネントを 入れ替え可能 / アップグレード可能 な独立したソフトウェアとして定義
  • サービス自身をコンポーネント化するため、サービスを複数のサービスへ分割する
  • コンポーネントとして用いる理由は、サービスが独立してデプロイ可能であるということ ( モノリシックなアーキテクチャでは、あるコンポーネントの変更がアプリケーション全体の再デプロイを必要とする )
  • サービスをコンポーネントとして扱うことで、インターフェースがより明確になる

ビジネス遂行能力に基づく組織化

  • サービスはビジネス領域に対応し、UI、データストレージ、外部連携など、幅広いスタックの実装が必要となる。 結果、チームは機能横断型 ( cross-functional ) であり、開発のために必要な全ての範囲のスキル ( UX、DB、プロジェクト管理 … ) をチーム内に含むことになる

プロジェクトではなくプロダクト

  • 大部分のアプリケーション開発は"期限のあるプロジェクト"として管理され、完成後、運用チームに引き渡され、プロジェクトチームは解散する
  • マイクロサービスでは、チームは製品のライフサイクル全体の責任を持つ ( Amazon の you build, you run it )
  • サポートの責任を追うことで、開発者がソフトフェアの振る舞いやユーザとの接点を増やし、ビジネス遂行能力を高めることにつながる

スマートなエンドポイントとダムパイプ

  • マイクロサービスは出来るだけ疎結合であることを目的とする
  • それぞれが独自のドメインロジックを持ち、リクエストを受けて、適切なロジックを実行し、レスポンスを返す
  • 複雑なプロトコルではなく、REST 的な単純なプロトコルを用いる
  • RabbitMQZeroMQ などの軽量なメッセージングも用いられる

分散統治

  • 中央集権的な統治は、単一の技術への統一へ向かう傾向があり、この手法は行き詰まる
  • 全ての問題が"釘"ではなく、全ての解が"ハンマー"ではない
  • 単純なレポートページを構築するために Node.js を使っても良いし、リアルタイム性を求められるコンポンーネントでは C++ を使っても良い
  • コンポーネントのデータ読み出しの振る舞いによって、適したデータベースを使い分けても良い
  • “できる"からと言って、それを"すべき"とはならない。 選択肢があるということ

分散データ管理

  • モノリシックなアプリケーションが単一の論理データベースをデータの永続化のために用いることに対し、マイクロサービスではデータストレージを分散させる
  • マイクロサービスは各サービスがおのおの所有するデータベースを管理するようにし、異なるインスタンスが同じデータベース技術でも全く異なるデータベース技術でも構わない
  • データの分散管理はデータの更新管理にも影響を与える
  • 複数のリソースを更新する際、一貫性を保証するためにトランザクションを用いる
  • このようなトランザクション処理は、複数のサービスに対する一時的な結合を強制する
  • 分散トランザクションは実装が難しく、結果としてマイクロサービスはサービス間でのトランザクション処理は行わずにすむ方法を重要視する

インフラの自動化

  • マイクロサービスは、継続的インテグレーション、継続的デリバリの豊富な経験を持つチームにより構築され、インフラを自動化する
  • ソフトウェアがちゃんと動作するという確認のため、十分な自動テストを行う
  • 新しい環境への自動デプロイも行う

障害のための設計

  • コンポーネントとしてサービスを使用する結果として、アプリケーションは各々のサービスの障害に耐えられるように設計する必要がある
  • 任意のリクエストで、サービスの提供元が稼働していないコトが原因で失敗する可能性があり、クライアントはできるだけうまく、この状況に対応する必要がある
  • これはモノリシックな設計に比べて不利な点で、対応のために複雑さを許容する必要がある
  • サービスはいつでも失敗する可能性があるため、素早く障害を検知し、可能であれば自動的にサービスを復旧することが重要
  • マイクロサービスはアプリケーションのリアルタイムな監視に重点を置く

進化的な設計

  • サービスの分割により、開発者は変化のスピードを落とすことなく変更をコントロールできる
  • コンポーネント化する際に、どのように分割すべきかの決断に直面するが、関連するモジュールに影響を与えず、コンポーネントを書き換えられるポイントを探す必要がある
  • コンポーネント化することで、より粒度の細かいリリース計画を立てることが可能
  • モノリシックな場合、どんな変更もフルビルドとアプリケーション全体のデプロイを必要とするのに対し、マイクロサービスは変更したサービスのみを再デプロイすればよい。これにより、リリースプロセスを単純、高速にすることができる

終わりに

ということで、つらつらと書かせていただきましたが、マイクロサービスの概要や特徴をつかむことは出来ましたでしょうか?

お気づきの方も多いとは思いますが、マイクロサービスだから良い、モノリシックではダメだというコトはありません。 

マイクロサービスでは、アプリケーションを構成する個々のサービスを独立したプロセスで実行するため、細かくスケールするコトが可能で、デプロイも容易で、変更に対する影響範囲を絞る事も可能です。 つまり、ビジネスの変化の速度にあわせ、柔軟に変化させるコトが可能というわけです。 そのトレードオフとして、アプリケーション全体の設計が複雑になる、通信オーバーヘッドが大きくなる、運用管理が大変になるといったデメリットもあります。

次回は、マイクロサービス適用の勘所として、どのような場合にマイクロサービスを適用すべきかについて、マイクロサービス登場の背景とあわせて書きたいと思います。

ではまた次回。