RailsConf 2008におけるMagLevデモで(参考記事)、Gemstoneの分散VMテクノロジーが発表された。このテクノロジーは、複数のGemstoneのVM間で同じオブジェクトメモリーを透過的に共有することを可能にする。
Terracottaは、それと同じようなことを可能にするJavaテクノロジーである。Fabio Kung氏は、JRubyでTerracottaを利用する実験を開始した。過去に、似たようなプロジェクトが試みられている。また、GemstoneはJavaベースの製品上でJRubyのサポートを試みたことや(参考記事・英語)、過去にTerracottaでのJRuby(リンク)の試みもあったが、最近は更新されていない。
我々は、このプロジェクトについてFabio Kung氏と話をした。Fabio氏は、JRubyとTerracottaを連携させる取り組みに関わることを「JMaglev」と呼んでいる。そして、その実現に先立って、いくつかの問題を解決する必要がある。
最初に、Fabio氏は実装についてと、JRubyを機能させるためにどのような修正が必要かについて説明している。
私は、JRuby内部をすべてのクラスタノードで共有できるようにするためにTerracotta POJOクラスタリングを利用しています。実際、各ランタイムには次のようなグローバル変数の集合があります。
public class Ruby { // ... private GlobalVariables globalVariables = new GlobalVariables(); }および:public class GlobalVariables { // ... private Listvalues = new ArrayList ();
}
Terracottaは単にこのグローバル変数リストをクラスタリングしています。このリストへのどのような変更も、クラスタ内のすべてのJRubyランタイムに複製されます。長所は、_いかなる_ rubyオブジェクトでもこのリストに追加できることです。regexp、hash、procのような複雑なオブジェクトさえも追加できます。すべてのグローバル変数が自動的に共有され、グローバル変数によって参照されるどのようなオブジェクトも、クラスタリングするためにTerracottaによってインストールメントされます。
それをサポートするために、JRubyに「クラスタリング可能」にするためのパッチを当てる必要がありました。実際、JRubyのあらゆるrubyオブジェクトがrubyランタイムへのハードリファレンスを保持しています。共有されるオブジェクトは多くの異なるランタイムで使用されるため、JRubyはある種のランタイムのアタッチメント/デタッチメントをサポートしなければなりません。そのように機能させることはできましたが、1つのJVMにつき1つのRubyランタイムだけでした。この部分にまだ、未解決の議論すべき問題があります。一部を次に挙げます。
- グローバルオブジェクト識別子: object_idをすべてのノードで同じにすべきか? - 共有メタクラス: オブジェクトクラス、スーパークラス、またはインクルードされているモジュールがさまざまなノードで変更されるとどうなるのか? - 1つのJVMあたりの複数のランタイムのサポート
私はこれらの問題のすべてについてシンプルなソリューションを採用しましたが、それぞれのソリューションにブログ投稿が必要になります。 ;-)
Fabio氏は、JRubyとTerracottaについて考えられるユースケースについて説明している。
TerracottaのHigh Availability(高可用性)モードと連携して、「JMaglev」(もっと良い名前が必要かもしれません)は、Rubyコードに立ち入らない信頼できるmemcachedの代替手段になることができると思います。しかし、実施すべき取り組みが多数あります。ですから、私はそれを公開しているのです。ご希望の方は誰でも貢献できます。
http://github.com/fabiokung/clustered-jruby/
Terracottaでは多数のサーバーを構成できます。1台が「マスター」(アクティブサーバー)となり、その他のサーバーはホストスタンバイモードになります。ここが、より面白くなってくるところです。なぜなら、アクティブサーバーが故障すると、他のサーバーが自動的に引き継いで可用性を高めるからです。TerracottaのEnterpriseバージョンでは、複数のアクティブサーバーを可能にするモードも利用可能です。memcachedでも似たようなことが達成されますが、memcachedはオブジェクトを永続化しません。
Terracottaは、分散キャッシュとして機能することが可能ですが、Javaシリアライゼーションを使用しません。単に変更内容を複製します。あなたはただ、データベースから取り出したオブジェクトをすべてのクラスタノードに共有させるだけです。JMaglevでは、つまり、それらをglobal variables - $shared = Person.find(:all)に置くだけでよいということです。
その他の考えられるユースケースは、Railsアプリケーションにおける多数のプロセスやマシン間でのHttpSessionの共有です。RailsアプリケーションをJRubyにデプロイしている人は、すべてのクラスタノードでHttpSessionsの共有を維持するために、透過的なクラスタリングされたオブジェクトを使用することが可能です。
実際、Terracottaのどのユースケースも、JMaglevのユースケースです。正直なところ、私は、実行可能だから単に実行しているだけです。Avy Briant氏のMaglevのケースとかなり似ています。Avy氏は、SmallTalk VMを使用してRubyコードを実行することが可能だと言い、その後Gemstoneのスタッフらは彼に連絡し、実際にそれができたということを証明しました。 ;-)
「JMaglev」に関して、よりクリエイティブなユースケースを私が得ることよりも、人々がよりクリエイティブになることを期待しています。
分散オブジェクトメモリーは、Gemstone/S(およびMagLev)の機能の1つにすぎない。もう1つの重要な機能が永続化である。GemstoneのMonty Williams氏が最近のエピソード(Rails Podcast)で説明しているとおり(リンク)、Gemstone/Sは、オブジェクトメモリーの永続化をサポートする。つまり、ORMやRDBMSでさえデータを保存する必要がないことを意味している。
「JMaglev」が似たようなことをサポート可能かどうかの問いに、Fabio氏は次のように説明している。
共有されるrubyオブジェクトはすべてTerracotta Serverに存在します。Terracotta Serverはこれらのオブジェクトを、シリアライズ可能でない場合ですら自動的に永続化できます。クライアントはスタブを実際の共有オブジェクトに保持します。あなたは、サーバーを永続化モードに設定するだけでよいのです。まだテストしていませんが、それはXMLコンフィグレーションの1行になるはずです。
JRubyオブジェクトを永続化するためにOODBとしてTerracottaを使用できると思いますが、現在のところそれは主要目的ではないと思います。Terracottaは、フェイルセーフで可用性の高いデプロイのために存在する、High Availabilityモードによってすでに共有オブジェクトを永続化しています。
http://www.terracotta.org/web/display/docs/Configuring+Terracotta+For+High+Availability.
TerracottaのWebサイトには、多くのTerracotta Integration Module(TIM)が記載されており、その一部は人気のORMソリューション用である。これらが永続化に役立つかどうかという問いに、Fabio氏はTIMには異なる役割があると説明している。
Terracotta Integration Module(TIM)は、共有オブジェクトの自動永続化とは関係していません。TerracottaとORMフレームワークとの連携に役立っているだけです。たとえば、hibernate TIMは、永続化とは何も関係ありません。このTIMは、Hibernateがほとんど努力せずに、JBoss TreeCacheやmemcachedのような真の分散キャッシュに働きかける必要なく、クラスタリングされた(分散された)EhCache(およびその他)を使用できるようにします。
Fabio氏はJRubyとTerracottaによる共有がどのように機能するかを示すスクリーンキャストを公開した(リンク)。これを試すには、GithubにあるFabio氏のclustered-jrubyリポジトリを参照すれば(リンク)、必要なすべてのものが提供されている。
原文はこちらです:http://www.infoq.com/news/2008/11/terracotta-jruby-jmaglev