Clojure記事紹介百日修行(2):「Soundcloud.comにおける大規模環境でのClojure利用」
https://soundcloud.com というサイトではClojureが使われているようで、そこでの利用方法に関する記事がありました。
要約:
大規模なシステムでは、複数の外部/内部サービスに依存するのは良くあること。このとき問題となるのは、
- 複数の外部サービスに依存するコードの複雑さを避けること
- 外部サービスのどれから落ちたときに、gracefulにdegrade出来ること
- さらにシングルスレッドプールが原因でシステムがレスポンス不能になることを避けること
これらの問題を解決するためのテクニックの紹介です
この記事で紹介してるライブラリ:
- josephwilk/circuit-breaker · GitHub
- https://github.com/Netflix/Hystrix
- Hystrix/hystrix-contrib/hystrix-clj at master · Netflix/Hystrix · GitHub
- josephwilk/hystrix-event-stream-clj · GitHub
- Netflix/Turbine · GitHub
- ztellman/aleph · GitHub
- ReactiveX/RxJava · GitHub
耐障害性 & モニタリング
外部のサービスやリソースに依存する場合、それらはかならずいつか落ちるという前提でシステムを構築する必要があります。 Clojureの場合、HTTPクライアントライブラリのデファクトはhttp-kitですが、これは アクセスの遅延評価のためにfutureを使っています。futureは単一のスレッドプールを使いますので(プール内のスレッド数は調整できますが) 外部サービスが落ちたときには、future全体がブロックしてしまいます。
解決策として、
- circuit-breakerを使う
- http-getのfutureに対して、@を使うのではなくderefを使う
- HystrixはNetflixが開発しているJavaのライブラリで、Clojure bindingもあります
等が上げられています。特にHystrixは、単なるCircit-breakerパターンにとどまらず、モニタリングもサポートしてる強力なライブラリのようです。
Composition Complexity
それぞれのAPI endpointからはHystrixの結果が出力されていますが、それらを一括して監視するためにTurbineを利用。
複数のサービスからの結果を合成して答えを返すようなコードでは、複数のリクエスト先に非同期にリクエストを出してレスポンスを合成する処理のため、コードが複雑になりがちです。ここでは、(最近流行の)リアクティブプログラミングであるRxJavaNetty/Alephと組み合わせて使っているそうです。