気の向くままに書き綴る

勉強会参加したメモや日々の思ったことのメモ等

Why we chose microservices?

2014年7月2日にPostされたBlogを読んだ。タイトルはBlogの小項目の抜き取ったものなの。

 

Blogと一緒にこのBlogのランディングページを確認すると、KarmaというWiFiルーターをレンタル(?)しているスタートアップ企業だと思う。

 

Blogにもあるけど、「ユーザーがStoreからWiFiルーターを申し込んで、FedExからWiFiルーターが届くといったシンプルな仕組み」らしく、設立当初はフロントとバックエンドでチームを分けてアプリケーションを作っていたらしい。

 

しかし、ビジネスがスケールしていく中で、一枚岩のバックエンドでは、手に負えない状況になっていく。それに対してどうアプローチしていったかがわかる。

 

microservicesをやりたくて行ったものという話よりかは、「自分たちでアジリティを出すために、どう改善していったか。」そして気がついたらmicroservicesだった。という印象をうけた。

 


How we build microservices at Karma | Karma

 

どのように私たちはKarmaでmicroservicesを構築したか

microservices、microservices architectureは、developerでHotなバズワードだ。しかし、具体的な例はまだ不足している。
そこで、過去数年間にわたるKarmaでのBackend APIのmicroservicesの取り組みが役立つかもしれない。

それは正確な「How to」より「why to」「wherefore-to」というようなものである。

microservicesが自身のApplicationに適しているかどうか、いくつかHintになると思う。そして、どのように適用していくか考えるきっかけになると思う。

なぜmicroservicesを選んだか?

Karmaを始めた時、私たちは、主に2つの部分(Backend API、Frontend Application)にプロジェクトを分割することを決めていた。

Backendは、店舗からの注文処理、使用量アカウンティング、ユーザー管理、デバイス管理等に責任をもつ。同時にFrontendはBackend APIにアクセスするユーザーのためのダッシュボードを提供する。

このことから我々はもし全体のBackend APIがモノリシックであれば、すべてがもつれて、うまく機能しないことに気づいた。

 

例えば、私達はユーザ、デバイス、及び店舗を持っている。
想像できるように、ユーザーは店舗からデバイスを購入する。
それは簡単に聞こえる。

 

しかし、一個のApplicationだった時、User関連のコードがDevice APIで終わり、Store APIは、Device APIを裏側で実行し、実際のスタッフが動く。

それは、「何がどう動いて」、「何が触れ」、「何が変わった」か追跡することは困難だ。

 

私たちは、Library毎にモノリスを分離し、一つのAPIとして組み合わせていた。

 

しかし、そのアプローチには3つの主要な課題があった:

  • Scaling

スケールするときは、一度に全体のAPIを拡張しなければならない。

Karmaの場合には、UserとDeviceのAPIはStore APIよりもはるかに高速スケールする必要があった。

 

  • Versioning

Libraryアプローチでは、単一の依存がApplicationのBackend全体をHoldする。
例えば、Rails3からRails4へののアップグレードは難しいです。すべてのコードが複数のプロジェクトにまたがっているからだ。

現在私達は、一度にすべてを更新する必要はありません。実行中の古いAPIを残して、必要なタイミングでそれらをアップグレードすることができます。

 

  • Multiple languages and frameworks

今、私たちは主にRuby屋だ。しかし、私達は新しい技術と言語の実験することが出来るようにしたい。
現在は、GoやClojureを利用している。なぜなら、すべてのサービスは、REST APIを公開しているからだ。コミュニケーションに問題はない。(最終的にすべてHTTP通信だからだ)

 

microservicesの最大ブーストはProgrammerの生産性である。
頭の中で全体のことを維持する必要ない!すべての目移りを取り除く。

 

どう始めたか 

Backendの大きなApplicationを細かくピースに分離することから始まった。
この動きは、私達にとって学ぶことができ、とても大きかった。
Applicationを作っていく中で、私達は課題に対して精通し、Applicationの側面で必要な境界が明白になった。

 

そしてどのようにApplicationを分割すべきかクリアになり、サービスに当てていった。

 

最初は、比較的大きかった分割だったが、他のmicroservicesの採用と同じように、私たちはそれらを小さく、小さくすることができた。

 

例えば、大きなApplicationである「Store」から始まった。
その後、取り扱い及び出荷機能を分割。
その後、出荷が別々の分割出来ることを発見した。
その後、出荷トラッキングが最初の場所でそれを出荷するのと異なる役割であることがわかった。

店舗は、現在3つのAPIで構成されています。

私たちの次のステップは、より多くの処理順序を分割することであるかもしれません。
私達は常に最善の方法を学習している。

microservicesは私たちにその柔軟性を提供します。最終的に、microservicesは、単一責任していくことが一番良い。(サードパーティの依存関係のほとんどを包み、Applicationが他のApplicationについて考える必要がない状態である)

 

microserviceを1,2週間で構築/再構築し、他のApplicationの書き換えを必要としない。
依存関係の更新以外で二年前に書いた「Collector」はそれ以来触れていない。

What our architecture looks like now

microservicesにはHTTPとメッセージキューの2つのコミュニケーション手段がある。
私達はBackend側をHTTPでsinatraを用いるところから始まった。サービスは、相互にURL介してメッセージを渡す。これは、処理が必要なタイミングで行え、非常に良かった、
しかし、これは指数関数的に複雑になっていった。
たとえば、オーダーが来て、それが出荷される必要がある。

それは十分に簡単ですが、もし私たちは注文が受信された後に複数の処理を行いたい場合は?

 

ストアは、請求書の話をする必要がある。またはメトリクスやメーラーAPIを使いたい場合があります。

つまり、Store Application内のエコシステム全体で多くの知識をパックしている。
それは、​​動作するのが困難になる。だから我々は、Event-baseでタスクの一部を分割し始めた。

 

私たちは、Publishing EventsとしてAmazon SNS(Simple Notification Service) を利用する。そして、Amazon SQS (Simple Queue Service) でEventを格納する。


SNSは、サービスに渡されたメッセージを受け取り、SQS経由で適切なキューにそれをPublishしている。

 

Microservicesは
・キューからジョブを取得
・処理
・成功した場合、ジョブを削除
プロセスが失敗した場合は、メッセージをキューに戻り、別のインスタンスのProcessが取得しにいく。

f:id:koudaiii:20150207021527p:plain

当社のプラットフォーム·アーキテクチャの簡略図

 

新しいマイクロサービスをデプロイする時、設定ファイル(listen message,type説明)と公開したいメッセージのタイプが含めている。「Fare」と呼ばれる設定内容を読み取る社内のツールを持っていて、適切なSQSやSNS·キューを設定する。

 

注文が来た時に、「注文が来ました、ここに詳細があります。」Eventが公開される。出荷Applicationは、メッセージングシステムを見に行く。

 

注文の詳細を見て、メッセージを出す。「Okay、私はこの人に2箱を送信する必要があります。」その他のサービスは、注文のEventを見て必要な作業を行うことができる。

そして、Store APIはそれを心配する必要はありません。
私たちはログイン処理や(WiFIの)カバレッジマップのような即時応答が必要な部分はHTTPで行っている。

サービスが要求しているのか語っているかどうかで決まる。もし要求しているのであれば、それはおそらく、即時応答を必要としている

Challenges we've faced

microservicesの最大の課題はテストです。
通常のWeb Applicationはエンドツーエンドテストが容易である。(ウェブサイト上のどこかをクリックして、データベースの変更内容を確認するような。)

しかし、私達の場合は、アクションと最終的な結果を最終的に確認することは困難だ。
問題は、泡のように連鎖し、どこで間違ったのか?それは、我々はまだ解決していないものだ。


かわりに、可能な限り各コンポーネントを良好に作ることを焦点に当てている。
そして、それぞれのmicroserviceが契約を履行するようにしている。
「いつ処理を行い、いつ返り値を得るか」手動でそれらが満たされていることを確認する。
暗黙的であり、それをテストするための自​​動化された方法を考え出していない。

この結論は、個々のApplicationがある時点で失敗することを想定して全体のApplicationを構築する。この構造は、局部的な問題を意味し、広がることはない。

一部落ちたApplicationがあった場合、そのApplicationと依存関係する部分に影響を与えるが、他のものをブロックしない。キューのおかげで、壊れたサービスは一度中断した場所から拾うことができる

On to the next thing

だから、私たちのアーキテクチャは今のところ...のようになります。
常に改善する方法を探している。


あたなたは私達のmicroservicesへの道のりの進化を見ることができる。
私たちは違う場所へ到達出来ると思う。Fareのような私達が作成したツールをいくつか持っている。そしてそれをオープンソースとして公開したいと思う。

microservices は銀の弾丸ではない。そして、すべてを解決するものではない。しかし。Karmaで偉大な作業をしている。きっとあなたののプロジェクトでも役立つだろう。