2015-10-23 6 views
10

私は、Scala jarファイルにDataFramesをパッケージ化し、Rでアクセスできるようにしたいと考えました。最終目標は、特定の頻繁に使用されるデータベーステーブルにアクセスする方法を作成することでしたPython、R、およびScalaでそれぞれ別のライブラリを書くことなくSparkR JVMを使用してScala jarファイルからメソッドを呼び出す

これを行うには、Scalaでjarファイルを作成し、SparkSQLライブラリを使用してデータベースにクエリを行い、必要なDataFramesを取得する関数を使用しました。 SparkはすでにRのJVM上で動作しているので、別のJVMを作成せずにこれらの関数をRで呼び出せるようにしたかったのですが、JVM Sparkの使用はSparkR APIで公開されていません。これをアクセス可能にしてJavaメソッドを呼び出し可能にするために、SparkRパッケージで "backend.R"、 "generics.R"、 "DataFrame.R"、 "NAMESPACE"を修正し、パッケージを再構築しました。

"backendこれらの機能をも含むようにgenerics.Rを 『:『私は修正

setMethod("callJMethod", signature(objId="jobj", methodName="character"), function(objId, methodName, ...) { 
    stopifnot(class(objId) == "jobj") 
    if (!isValidJobj(objId)) { 
    stop("Invalid jobj ", objId$id, 
     ". If SparkR was restarted, Spark operations need to be re-executed.") 
    } 
    invokeJava(isStatic = FALSE, objId$id, methodName, ...) 
}) 


    setMethod("newJObject", signature(className="character"), function(className, ...) { 
    invokeJava(isStatic = TRUE, className, methodName = "<init>", ...) 
}) 

形式手法』:

#' @rdname callJMethod 
#' @export 
setGeneric("callJMethod", function(objId, methodName, ...) { standardGeneric("callJMethod")}) 

#' @rdname newJobject 
#' @export 
setGeneric("newJObject", function(className, ...) {standardGeneric("newJObject")}) 

その後、私は、これらの機能のために輸出を追加しました.RはcallJMethod『と』createJObjectを」私が作りました』 NAMESPACEファイル:

export("cacheTable", 
    "clearCache", 
    "createDataFrame", 
    "createExternalTable", 
    "dropTempTable", 
    "jsonFile", 
    "loadDF", 
    "parquetFile", 
    "read.df", 
    "sql", 
    "table", 
    "tableNames", 
    "tables", 
    "uncacheTable", 
    "callJMethod", 
    "newJObject") 

これにより、新しいJVMを起動せずに私が書いたScala関数を呼び出すことができました。

私が書いたスカラーメソッドは返されたときにRの "jobj"であるが、SparkR DataFrameは環境+ jobjであるDataFramesを返します。これらのjobj DataFramesをSparkR DataFramesに変換するために、私は上記の手順に従ってアクセス可能にした "DataFrame.R"でdataFrame()関数を使用しました。

私は、RからScalaで "構築した" DataFrameにアクセスし、SparkRのすべての機能をそのDataFrameで使用することができました。このようなクロスランゲージ・ライブラリを作る良い方法があるのか​​、Spark JVMが公開されるべきではない理由があるのか​​どうか疑問に思っていましたか?

答えて

4

Spark JVMは公開しないでください。

複数の可能性があります。 Spark開発者は、安定した公開APIを提供するために真剣な努力をしています。ゲスト言語がJVMとどのように通信するかを含む実装の詳細は、単純に契約の一部ではありません。ユーザーに悪影響を与えることなく、いつでも完全に書き換えることができます。あなたがそれを使用することを決めた場合、後方互換性のない変更があなた自身であります。

内部をプライベートにすると、ソフトウェアの保守とサポートの労力が軽減されます。あなたは、ユーザーがこれらを悪用する可能性のあるすべての可能性のある方法であなた自身を気にする必要はありません。

、クロス言語ライブラリ

を作るためのより良い方法あなたのユースケースについての詳細を知らなくても言い難いです。少なくとも3つのオプションがあります:

  • はじめにRは弱いアクセス制御メカニズムを提供します。 APIの一部が内部にある場合は、常に:::関数を使用してAPIにアクセスできます。スマートの人々は言う:

    対応するオブジェクトは、おそらく 正当な理由のために内部に保持されている ので、あなたのコード内で:::を使用するために、一般的な設計ミスです。

    しかし、確かにそれはスパークソースを変更するよりはるかに優れています。ボーナスとして、あなたのコードの中で特に脆弱で潜在的に不安定な部分を明らかにマークします。

  • あなたが望むすべては、最も簡単なものは生のSQLを使用することであるデータフレームを作成する場合。それは清潔で、持ち運び可能で、コンパイルやパッケージングを必要とせず、単に機能します。

    sql(sqlContext, q) 
    fooDF <- sql(sqlContext, "SELECT * FROM foo") 
    

    のPython:

    sqlContext.sql(q) 
    fooDF = sqlContext.sql("SELECT * FROM foo") 
    

    スカラ:

    sqlContext.sql(q) 
    val fooDF = sqlContext.sql("SELECT * FROM foo") 
    
    あなたは以下のことがRで使用することができq

    CREATE TEMPORARY TABLE foo 
    USING org.apache.spark.sql.jdbc 
    OPTIONS (
        url "jdbc:postgresql://localhost/test", 
        dbtable "public.foo", 
        driver "org.postgresql.Driver" 
    ) 
    

    という名前の変数に保存されているようなクエリ文字列を持っていると仮定すると、

    またはSpark SQLで直接実行できます。

  • Spark Data Sources APIを使用すると、プラットフォーム間で一貫したアクセスが可能になります。

これら3つのうち、私は複雑なケースではデータソースAPIを優先し、内部を最後の手段として残したいと考えています。

編集(2016年8月4日)

あなたはJVMへの低レベルアクセスに興味があるなら内部SparkRのRPCプロトコルを公開する比較的新しいパッケージrstudio/sparkapiがあります。それがどのように進化するかを予測するのは難しいので、あなた自身の責任でそれを使用してください。

+0

しかし、RとScalaの間でデータを共有し、データを保存せずに再読み込みする良い方法はありますか?私が何か解決策2と3が不足していない限り、両方がそれを必要とするようです。 – shj

+0

私はあなたが何を望んでいるか正確にはわかりません。 Sparkは、JVMあたり複数のコンテキストをサポートしていません([SPARK-2243](https://issues.apache.org/jira/browse/SPARK-2243)を参照)。また、コンテキスト間でRDDを共有することもできません。したがって、3つのタイプすべてでは、あるタイプのストレージからデータを読み取る必要があります。 [spark-jobserver](https://github.com/spark-jobserver/spark-jobserver)、["shared" RDDs(https://ignite.apache.org/features/igniterdd)]のようないくつかのオプションがあります。 html)をIgniteの上に置くか、この問題に対処しようとしているメモリ記憶層として[Tachyon](http://tachyon-project.org/)を使用していますが、単純なJVMの公開はどこにもありません。 – zero323

+0

単純なSQLクエリの場合、おそらくbool-in [Thrift server](http://spark.apache.org/docs/latest/sql-programming-guide.html#running-the-thrift-jdbcodbc-server)を使用できます。 – zero323

関連する問題