14
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Microservicesアンチパターンについて ①

Last updated at Posted at 2019-02-07

業務でモノシリックなTransactionScriptで書かれたアプリケーションをマイクロサービスに移行しようと検討している中で、下記の学術記事を読んだ。
Microservices antipattern and pitfalls

知識整理のためにまとめる。

Data-Driven Migration AntiPattern

  • モノシリックなアプリケーションをマイクロサービスに移行する場合にやりがちなアンチパターン。
  • モノシリックなアプリケーションを機能的に分離すること。そして、その分離したサービスのみに所属したデータベース(スキーマ)を巨大なデータベースから分離していくこと。この二つがゴールとなる。
  • とりあえずアプリケーションのモジュールとデータベースを分割して、マイクロサービスに移行しようとしても、それは歪で、移行のコストは高くなっていく。

About Microservices

  • マイクロサービスなシステムは小さく、一つの関心事のみのために作られる。そして、それぞれのマイクロサービスはそれぞれのデータのみを保有する。
  • マイクロサービスは、自分自身に境界付けられたコンテキストのみをサポートし、他のマイクロサービスと何も共有せず、ただ定義されたインターフェースを公開し、何にも依存しない。
  • 上の定義に従えば、テスト・開発・デプロイは容易なものになる。

Functionally First, Data Last

  • データベースの分割は、ソースコードの分割よりも複雑で困難。
  • まずは機能的にモジュールを分割していく。そして機能的にその切り離したマイクロサービスの関心事が最小になったところで、そのサービスが処理するリクエストやモデルを分析し、切り離したサービスのみが扱うデータベース(スキーマ)を切り出す。
  • この方法が最も移行のコストを下げる方法。

DataAnti.png

The Timeout AntiPattern

About Microservices

  • マイクロサービスアーキテクチャは各サービスが定義されたプロトコルを使用して互いに交信しあう。
  • マイクロサービスアーキテクチャの困難の一つにサービス間の可用性・応答の管理がある。

Using Timeout Value

  • Consumerであるマイクロサービスが接続もしくは購読をしている最中にPublish側サービスからの応答が来なくなった場合、Consumerサービスは無期限に待機するか、定義されたリトライ回数分のリトライを行うだろう。
  • こういう場合、Publish側が配信を行っていないことはどうすればConsumerは確認できるか。この場合、よく使われるのはタイムアウト値を設定することである。
  • しかし、タイムアウト値には欠点がある。例えば、サービス間の平均通信レイテンシが1000msだとして、最大レイテンシは5000msだとする。タイムアウト値を5000 × 2 = 10000msと設定したとすると、ユーザーがエラーだと気づくまでに10秒かかることになる。これがタイムアウト値設定の場合の欠点。
    でも、これそもそものレイテンシ遅くない。。?

Using The Circuit Breaker Pattern

  • 次はサーキットブレーカという死活監視をサービス間に置く方式。

  • サーキットブレーカは何らかの方法(ping,etc..)でPublishサービスの状態を監視し、もしPublishが応答を返さなくなったら、サーキットブレーカを通過していたConsumerからの通信対して、Publishサービスが応答を返さなくなったことを伝える。
    circuitAnti.png

  • サーキットブレーカパターンはいくつかの著名なOSSでも使われている方式で、タイムアウトはアンチパターンとなっていた。

The "I was Taugut to share" AntiPattern

About Microservices

  • オブジェクト志向プログラミングで作られたアプリケーションでは、文字列を扱うユーティリティや汎用的な計算ロジックを含んだ共通モジュールを、いくつかのモジュールで共通で参照する構成はよく見られる。
  • しかし、これはマイクロサービスにおいてはデプロイ・テストなどの容易性を実現するに当たって、障害となってしまう。ではどうすれば共通ユーティリティモジュールを100を超えるマイクロサービスでも共通的に扱えるようにすれば良いのか。

4Patterns

記事では4つのパターンが紹介されていた。

Shared Project
  • 共有ユーティリティをプロジェクトとしてマイクロサービスのプロジェクトと共有しておき、コンパイル時に動的にバインディングする方法。これは開発効率については有益だが、変更を誰がなぜ行ったのか、ということがわかりづらく、リリース間際になって共通ユーティリティの変更が破壊的な影響をサービスに与えてしまい、テストをし直すという状況にもなり得る。
shared Library
  • 共通ユーティリティをモジュールとして管理する方式。これは開発効率を損なう可能性はあるが、
    Shared Projectよりも優れている点はバージョン管理が可能ということ。サービスのオーナーはバージョンアップされたモジュールを使うか、現在バージョンのモジュールを使うが明確に判断が下せる。
Replicated
  • 共通ユーティリティを各サービスコンポーネントがそれぞれ保有する方式。これはDRYの原則には反するが、依存を外部に全く持たなくなるという点では有利。だが、この方式の欠点は共通ユーティリティにバグがあった場合、全てのコンポーネントの保有する共通ユーティリティを修正しなければならないということ。そのため、この方式をとる場合はその共通ユーティリティが変更が限りなく少なく、安定したモジュールである場合に限るだろう。
Consolidation
  • この方式は共通ユーティリティを分解して、サービスごとに特化した部分のみを各サービスに分離して含めるという方式。つまり事実上、共通ユーティリティを使わないという方式だと言っているように思う。これは使用している共通ユーティリティが頻繁に変更されるものであれば、検討しても良いかもしれない。

続く

今回は三つのアンチパターンとそれに対するプラクティスを記載した。

  • Data-Driven Migration AntiPattern
  • The Timeout AntiPattern
  • The "I was Taugut to share" AntiPattern

継続して投稿していこうと思います。

14
14
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?