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と組み合わせて使っているそうです。
Clojure記事紹介百日修行(1):「MetabaseがPythonからClojureに移行した理由」
Metabaseというオープンソースのソフトウェアが、PythonからClojureへ移行した際に、Clojureを言語として選定した理由が 記述されていました。要約して紹介します
Pythonで書かれたものから移行した理由
Metabaseの前進となった社内ソフトウェアは、PythonとDjango/Angularを用いた物だったそうです。
しかし、
- WSGIのリクエストモデルが、MetabaseのAPIのモデルと合わない
- MySQL、Postgresqlのドライバが要コンパイルだったためデプロイ・サポートが面倒
- ソフトウェア全体を構成する部品が多く、いろんなところが不安定だった。具体的には、Docker + nginx + uWSGI + Django + compiled drivers + search indexing (whoosh) processes + Celeryd + Celery workers + Redisのような構成だった
新しい言語への要請と候補
新しい言語(と構成)に求められることは、
- 非同期Webリクエストへの安定したモデル
- 簡単で早いデプロイ
- 生産性
- データベースドライバが多くて成熟していること
- クエリ言語のコンパイルを簡単にするため、強力な関数型の機能があること
でした。これらの要請に対し、候補は
・Java ・Scala ・Clojure ・Javascript/Node ・Go ・Python(twisted) ・Python(tornado)
まずPythonはそもそも外され、Go/Javascriptは指示する声はあったもののデータベスドライバが未成熟、Javaは好きではなく、残るはScalaとClojureでした。
Scalaをテストした後にClojureへ
最初は、世間の流行や開発者の多さからScalaを選んだそうです。しかし、Scalaのデータベースアクセスは厳密な型チェックを要求するため、動的にクエリ言語をSQLにコンパイルするMetabaseでは使いにくい部分があったそうです。
こうしてClojureが選ばれました。
Clojureを採用したメリット
当初想定していた要求に加え、Clojureの採用には思わぬメリットもありました。単一Jarによるデプロイは、Elastic Beanstalkと組み合わせることによってでぷろいが劇的に簡単になりトラブルも減ったそうです。さらに、デスクトップアプリケーションへの展開も容易となりました。これはPython+Redisのような構成では容易には出来なかったことです。
オープンソースソフトウェアであるMetabaseの開発者たちがClojureを採用した経緯についての記事を紹介しました。
Clojure Applied: From Practice to Practitioner
- 作者: Ben Vandgrift,Alex Miller
- 出版社/メーカー: Pragmatic Bookshelf
- 発売日: 2015/09/06
- メディア: ペーパーバック
- この商品を含むブログを見る
clojure.tools.namespace.repl/refreshがコケる
clojure.tools.namespace.replという非常に便利なライブラリがあり、コレを使うとREPLを再起動せずにプロジェクトの.cljファイルを読み直してくれる。単にリロードするので無く、既存のシンボルを削除し、依存関係を追跡して正しい順番で読み込んでくれるようだ。
ただ、手元で現在進めているプロジェクトで実行してみるとエラーとなってしまった。いろいろ調べた結果、まだ確証はないけれど、project.clj内で:mainを指定しているとダメなようだ。
もう少し調べる。