Pactのサンプルを動かしてみた

Constomr-Driven Contract PatternのPactのexampleを実施して動きを観察してみました。

GitHub: https://github.com/realestate-com-au/pact

対象

example/animal-service # service providerに対するテスト
example/zoo-app # service customerに対するテスト

zoo-app

zoo-app配下で、以下のコマンドを入力します。

$ bundle install
$ bundle exec rake spec

MockServerがService Providerの役割を担います。
Service Customerである ZooApp::AnimalServiceClient がテスト対象です。

ここのテストでは、CustomerがProviderに対して成立させたい機能のリクエストを送り、それに対してProviderが成功/失敗の応答を行うという振る舞いにたいしてexpectで結果を検証します。

Contractフェイズにおける、Customer => Providerへ使いたいサービスの契約を実施しようとするときのもののようです。

animal-service

animal-service配下で以下のコマンドを入力します。

$ bundle install
$ bundle exec rake pact:verify

Service Providerに対するテストなので、ProviderにConsumerに対するテストデータを保存しておき、Providerに対するリクエストに対して正しく応答ができるか、をテストしています。

そのため、想定したHTTPリクエストが正しく行われているか、が主なテストの合否判定になりますね。

締め

Customer-Driven Contracts Pattern自体、サービス間の関係性を確認するためのパターンです。そこに限ってテストを実施するのであれば関係性を確認するときのやりとりをテストすることに限定されそう。

Consumer-Driven Contractsを採用するのであれば、この関係性が破綻しないように正しくすることは必須要素なので、これのようなシンプルさがあったほうが良さそう。

なるほど。

以下のpactoも、振る舞いとしては同じことを確認しようとしてそうです。テストダブルとか、そこらへんの機能は必要性が増えたら見てみようと思います。

MicroServices Patternを読んでみた

こちらの、パターン集を集めている?Webサイトに載っていたので読んでみました。

http://microservices.io/patterns/microservices.html

Context and Problem

レイヤー分けされたり、hexagonal architectureをもつアプリケーションは、以下のようなコンポーネントから構成される。

  • Presentation compornents
  • Business logic
  • Database access logic
  • Application integration logic

このような様々なレイヤー分けされたサービスから構成されるシステムを(ざっくりと)マイクロサービスと呼ぶ。

これらの構成をもつアプリにおけるデプロイアーキテクチャはどのようなものか?

Solution

  • Scale Cubeなアプリケーションアーキテクチャ
  • 機能的に分解された多くのサービスの集合としてアプリケーションが動作する
  • サービスは、HTTP/RESTのような同期的なコミュニケーションと、AMQPのような非同期的なコミュニケーションを使う
  • サービスは、それぞれが独立して開発/デプロイされる
  • それぞれのサービスは、それぞれが分離するために自身のDBをもつ。それらのDBはレプリケーションやアプリケーションレベルのイベントで保守される。

Solutionの問題

  • 開発者は、モノリシックアーキテクチャ以上の、分散システムを構築するための複雑性を扱わなければいけない
    • IDEやツールの多くは、モノリシックアーキテクチャ向けのもの
    • Testingがより困難になる
    • サービス間の内部処理の実装が必要
    • それぞれの開発チーム間の連携を構築する必要がある
    • 分散トランザクションを使う必要が有る
  • デプロイが複雑
  • 個々のサービスが独立して起動、利用可能になるまでの時間が必要なので、サービスが利用可能になるまでに最大でサービス分のオーバーヘッドがかかる

類似

API Gateway pattern

APIを受け取るgatewayを境界に、Client/Serverで扱う処理を分散させる

Netflix APIのようなもの

Scale Cube

The Art of Scalabilityに記載されているパターン

アプリケーションのスケールを、箱型のXYZ軸のそれぞれの軸をもとに表現して説明したパターン

  • X軸スケーリング
    • Horizontal duplication
    • アプリケーションのクローンを増やすことでスケールさせる
  • Y軸スケーリング
    • Functional Decomposition
    • 1つのサービスを複数のサービスに分離させ、動作させること
  • Z軸スケーリング
    • Data partitioning
    • コードの独立したコピーをそれぞれのサーバーで動作させることで、X軸スケールのように動作させる
    • X軸との差は、このZ軸はデータのサブセットのみに責任をもつ

関連用語

AMQP

Advanced Message Queuing Protocol

KarmaのMicroserviceへの取り組みを読んでみた

KarmaのMicroserviceへの取り組みを読んでみた。

検索する限りでは、以下URLの企業のよう。

Microserviceにおける、個々のサービスがコミュニケーションする方法として以下の2通りを用いているそうな。

  1. Communicate each other with HTTP requests
  2. Communicate each other with a message queue

この中で、HTTPリクエストベースで、あるサービスから別のサービスへメッセージを投げる形をはじめはとっていたけれど、これはサービスが増加してきたらより複雑になってくるからmessage queueを使うようになってきたとか。

実現のため、Amazon SNSをイベントを配信するために使い、Amazon SQSをそれらイベントを蓄積するためにつかったそうな。プロセスが成功したらjobがQueueから取り出され、進行し、削除される。もしプロセスが失敗すれば、そのプロセスはqueueに戻ってくる。

新しいマイクロサービスが追加されたら、そのサービスはメッセージのタイプを受け取るか、何のメッセージを配信するかという設定ファイルを読み込む。Fareと呼ばれる内省ツールを使っている。

The Biggest Challenge is Testing とあるように、系として如何にテストするか、が大きな挑戦だと言っていたところが面白かった。

この記事のコメントのところに、Pactの話も出ていて、Consumer-Driven Contracts Design Patternはサービスごとの依存性を緩和する手段としてベストプラクティスになりつつあるのかなという感じを受けました。

Consumer-Driven Contracts Design Patternを読み漁ってみた

Microserviceのテストの話を調べていると、以下のような記事を見つけました。

Simplifying Micro-Service testing with Pacts

このPactoと呼ばれるツールがConsumer Driven Contractsと呼ばれるデザインパターンを使っていると書いていたので、同デザインパターンを少し調べてみました。

関連:

Consumer-Driven Contracts Design Patternをざっくりいうと

Consumer-Driven Contract patternは、Consumerが取得可能な必要なサービスをProviderと共有(規約)し、Customerごとに特定のサービスのみをProviderから利用可能にするパターンです。

特定のCustomerが使う機能をProviderから取得することで、Customerは限定された範囲の機能を利用します。CustomrはProviderにより提供されるであろう機能の取得を試み、契約(Contract)を成立させようとします。このとき、Customerが利用する機能の補助的な説明をProviderに提供することもできます。ここで契約が正常に成立すると、サービス実行時には基本的にCustomerは契約の成立した機能を使ってProviderからサービスを受けます。

Customerが使っている機能はProviderに適宜提供されます。ProviderはすべてのCustomerが利用している機能の規約の集合をもちます。

登場人物

  • Provider contracts
    • Providorから提供されているサービスに関する規約。XMLなどで記載される。
  • Consumer contracts
    • Provider Contractのうち、個々のCustomerが必要とする範囲の規約
    • 個々の消費者が必要とするサービスの契約
  • Consumer-Driven Contracts(消費者主導契約)
    • Service Providerが満たすべき全Consumer Contractsの集合を書いた規約

Summary of Contract Characteristics

MarfinFowler氏の記事のなかで、Provider,Consumer,Consumer-Drivenのそれぞれがどのような関係を持つものかをまとめたもの。

Contract Open Complete Number Authority Bounded
Provider Closed Complete Single Authoritative Space/time
Consumer Open Incomplete Multiple Non-authoritative Space/time
Consumer-Driven Closed Complete Single Non-authoritative Consumers

Pactsを使ったテスト

CustomerやService Providorに対するHTTPリクエスト/レスポンスをPactsが模倣して、その結果をRSpecを使いバリデーションする。そうすることで、Consumer-Driven Contracts Design Patternに登場してくる要素に対するテストを実施できるようにしているっぽい。

締め

SOAやMicroserviceでは、各々のサービスの依存関係や関係性が開発の妨げになることがおおいにあります。そいうのも、依存関係を持つサービスであれば、同時にデプロイするなどのように タイミング揃える ことが必要になるためです。それでは、高い開発速度を、それぞれのサービスチームが維持できません。

それに対して、このConsumer-Driven Contracts Design Patternは依存関係をデプロイ後に取得することでそのサービス同士の関係性を緩和させることが目的のようです。言われれば確かなのですが、これをちゃんと実装、運用するにはシステムの設計だったり、そのテストの構築が大変そう。

ともあれ、Service Discoveryのような位置付けですね。なるほど。

NetflixのHystrixにも使われるCircuit Breaker patternを調べてみた

Testing Strategies In A Microservice Architectureを読んだを読んでいる途中に出てきた、Circuit Breakerと呼ばれる機構を調べてみました。Martin Fowler氏がこの記事で言及しているものでした。

このCircuit Breaker patternは、Release It! 本番用ソフトウェア製品の設計とデプロイのためにで描かれているような、本番環境化において発生する、複数システムが関係するからこそ発生する障害を抑えることも目的としたデザインパターンのようです。「複数システムが関係するからこそ発生する障害」とは、一部システムの負荷が高まりタイムアウトするといったことを含みます。

内容自体は、 障害検出のための共有のオブジェクト(Circuit Breacker)を用意して、監視・検出できるようにする ということらしいです。NetflixのHystrixがその実装としてこのパターンを含んでいます。ちなみに、RubyだとここなんかがOSSの実装例として上がっていました。

Circuit Breacker Pattern

Circuit Breaker patternの考え方は単純で、以下の図のようにClientとSupplierの間にCircuit Breakder Objectを配置し、そのオブジェクトが障害のモニタリングを行いエラーを制御する、というものです。以下の図では、Circuit Breadker Objectが、Supplierのエラーを複数回検出すると、以降は復帰するまで必要以上にリクエストしないように制御します。

サンプルプログラムも置いていています。それを見ると、@failure_countのインスタンス変数にエラーの回数を足していき、一定数超えるとCircuit Openな状態にする。意図的にリセットされるとそのインスタンス変数がゼロになる、という処理で単純に書けますね。

Circuitの状態遷移は以下と定義されています。以下ではClose/Openの2値からさらにHalf Openというものも加え、Openな状態からresetされた後の復帰確認の状態を作っています。

この実装には、並列プログラムのデザインパターンであるFutures and promisesが良い知見を持っているそう。

Circuit Breakersのオブジェクトを設置することは、失敗するであろうオペレーションを抑制することができるところに価値があります。例えば、HTTPリクエストが30秒タイムアウトを繰り返す間、関連するサービスはそれを待たないといけないですが、そもそもCircuit Openな状態が既知であれば失敗することがわかっている処理に30秒も待つ必要がなくなるわけです。

締め

Breacker自体が障害になることもあるので、ClientはCircuit openな状態含めて適切な処理を実施する必要があります。一方で、Microservicesのような複数システムが連携する場合、監視・検出はシステムの品質を高めるために非常に重要な役割を担います。その仕組みを共通化してライブラリとして用意しておくことは価値が高そうです。

Broad Stack Testとは

Broad Stack Testに関して、Testing Strategies IN A Microservice Architectureを読んだで言及されていたので少し調べてみました。

Martin Fowler氏がこの記事にて言及しているテストタイプです。同記事では、end-to-end testや、full-stack testに似ていると書いています。

Broad Stack Testは、SelneiumやSahiのようなツールを使い、UI越しに実施されるテストだそうです。テストピラミッドにおいてもUIテストに区分されると書かれていたので、Microservicesにおいて末端のユーザが使うUI越しの操作をテストする、というテストタイプのようです。

なるほど。

Spring Cloud Netflixを読んだ

Springが、Netflixが公開している彼らのOSS群を説明している記事を読みました。ちょっと、記憶に止めておきたい内容を探っているのでそのメモがてら。

記事: http://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html

これは、Netflixのmicroservicesを構成するツール群を説明していました。

  • Service Discovery
    • Eureka Clients
  • Circuit Breaker
    • Hystrix
  • Intelligent Routing
    • Zuul
  • Client Side Load Balancing
    • Ribbon

Service Discovery: Eureka Clients

  • Service Discoveryはmicsoservicesベースのアーキテクチャとして大事な要素

Circuit Breaker

Hystrix Clients

  • Netflixは、CircuitBreakerを実装したもの。Microservicesでは、複数のサービスコールのレイヤを持っている。

  • 低レベルのサービス障害が発生すると、障害がユーザまで伝っていくので、障害のあったサービスをフォールバックすることで障害の伝搬を抑制することが目的

  • ↑の状態になるサービスは、例えば /health の応答として “CIRCUIT_OPEN”というstatusを返す

Dashboard

  • circuitがOpenかCloseかを知ったり、応答速度を監視するためのダッシュボードですね

Turbin

  • すべての /hystrix.stream エンドポイントを、Dashboardの /turbin.streadm エンドポイントに統合するアプリケーション。アプリのインスタンスはEurekaにある。

Declarative REST Client

Feign

  • Feignは、Web serviceクライアント

この記事では、Spring frameworkとして使える方法も紹介してました。

Client Side Load Balancer

Ribbon

  • クライアント側でのロードバランサ。HTTP、TCPベース。
  • Feignは常にRibbonを使うようになっている。

External Configuration

Archaius

  • クライアント側の設定ライブラリ
  • NetflixのすべてのOSSコンポーネントの設定で使われているらしい

Router and Filter

Zuul

  • microservice architectureにおけるサービスのルーティングを行う
  • JVMベースの、ルーティング + サーバ側ロードバランサを備えたライブラリ
  • 以下の機能を提供する
    • Authentication
    • Insights
    • Stress Testing
    • Canary Testing
    • Dynamic Routing
    • Service Migration
    • Load Shedding
    • Security
    • Static Response handling
    • Active/Active traffic management

以上。

Microservicesは基盤技術やツールや体制が充実していないと破綻することがよく言われるようになりました。今回のツール群をみるだけでも、保守や不具合解析以外にも、サービス間のつながりをどうするかとか、障害発生時もサービス全体として正しく振る舞うにはとか、そういう設計も重要な位置を占めていることが容易に想像できます。

事業に対するシステム構成上、Monolithicで十分であればそれに越したことは無いですね。。。

Testing Strategies in a Microservice Architectureを読んだ

2014年11月18日に公開された、Testing Strategies in a Microservice Architectureを読んでみました。Microservicesに対するテスト戦略に関する大まかな方針を書いています。想像した通りだったのですが、理解しやすく、例も記載しているので取り組む人はいったん読んでおいたほうが良さそうです。

目次

Some Definitions

  1. What is a microservice ?
  2. Anatomy: a loook inside a microservice
  3. Architecture: choreographing service

then the Testing Strategies…

  1. Unit: mockist vs classic
  2. Integration: datastores and eternal services
  3. Component: in or our of process ?
  4. Contract: ensureing consistency across boundaries
  5. End-to-end: tips and tricks

the some Conclusions

  1. Options: testing benefits of microservices
  2. Test Pyramid: how many tests?
  3. Summary: wrapping thing up

内容

以下、内容ですがいくつかピックアップする程度です。例もあるのと、ざっと読めば時間もかからないので読んでみることをお勧めします。

A microservice architecture builds software as suites of collaborating services.

  • microservicesは、いくつかのサービスの集合体
    • マイクロサービスは、REST over HTTPを使って統合されることが多い
    • 統合には、軽量なメッセージプロトコル、Pub/Subモデル、ProtobufやThriftのような通信が用いられる
  • Microsrvicesは、大抵は類似のモジュールを分割することができる
  • Microservicesは、ネットワーク上のデータストアなどに外部接続する
  • マルチサービスは、1つのシステムとして一緒に動作する

テストの話

実施されるテストを、テスト対象が小さなものから区分しています。

Unit testing

A unit test exercises the smallest piece of testable software in the application to determine whether it behaves as expected.

ポイント: テストするモジュールの関係性をテストするか、モジュール自体をテストするか

  • Sociable unit testing
    • モジュールの状態を得ることで、モジュールの振る舞い(Behaviour)をテストする
    • モジュールのインタフェースを通してテストする、ブラックボックステスト
  • Solitary unit testing
    • オブジェクト間の関係性や依存関係をテストする
    • テストダブル(test dubles)

Integration Testing

An integration test verifies the communication paths and interactions between components to detect interface defects.

  • Integration tests
    • いくつかのモジュールを集めたサブシステムをテストする
    • コミュニケーションパスなんかを確認する
    • サブシステム全体ではなく、テスト対象で閉じた範囲でのテストが目的
  • Whilst tests
    • レイヤー間のやりとりや、外部コンポーネントとのやりとりを検証するためのテスト
    • 外部コンポーネントとは、他のマイクロサービスであったり、データストア、キャッシュなど

データストアとの結合や、外部コンポーネントとの統合におけるフィードバックを素早く得ることが目的。

Component Testing

A component test limits the scope of the exercised software to a portion of the system under test, manipulating the system through internal code interfaces and using test doubles to isolate the code under test from other components.

  • Componentに閉じたテスト
    • 単一のコンポーネントにスコープを限定することで、テストの保守や実施を素早くする
    • テストダブルを使うことで、複雑な振る舞いを抑えたテストが実施できる
    • 異常系の再現だったりを作り出してテストできる
    • microservicesでは、
      • テストダブルで外部コンポーネントを置き換え、internal APIのエンドポイントを確認するとか
    • オプションとして考慮するところ
      • ネットワークや、メモリなどをどこまで考慮するかは考える必要がある

Internal resources are useful for more than just testing…

  • テスティングの側面として、監視、運用、デバッグなどに役立つ
  • health checkやPingは負荷分散なんかに役立つ

Contract testing

An integration contract test is a test at the boundary of an external service verifying that it meets the contract expected by a consuming service.

  • 外部との依存関係に注目したテスト
  • データ構造の入出力、副作用、パフォーマンスや平行性を見たりする
  • microservicesでは、public APIをインタフェースとしてテストされる
  • component testsは、サービスの振る舞い(behaviour)を深くみるのではなく、入出力のレイテンシーやスループットが許容範囲内かをみる程度、なのが異なることろ

End-to-end testing

An end-to-end test verifies that a system meets external requirements and achieves its goals, testing the entire system, from end to end.

  • システム全体のテスト
  • システム全体がビジネスゴールを満足するかを検証する
  • ブラックボックステスト
    • GUIsや、サービスAPIがPublicインタフェースとして検証される

Writing and maintaing end-to-end tests can be very difficult

end-to-endテストのガイドライン

  1. Write as few end-to-end tests as possible
  2. Focus on personas and user journeys
  3. Choose your ends wisely
  4. Rely on infrastrucrure-as-code for repeatability
  5. Make tests data-independent

Microservice architecrures provide more options for where and how to test

境界を定義することで、システムにおけるコンポーネントを見やすく、独立して扱いやすくする

The test pyramid helps us to maintain a balance between the different types of test

Unit => Integration => Component => End-to-end => Exploratory

Conclusion

http://martinfowler.com/articles/microservice-testing/#conclusion-summary

MicroservicePrerequisitesのメモ

最近、Microservicesの話題が盛り上がっていますね。
http://martinfowler.com/articles/microservices.html

その中で、Martin Fowler氏があげているMicroservicePrerequisitesについて、メモがてら。

Continue reading “MicroservicePrerequisitesのメモ”