Я хотел иметь возможность упаковать DataFrames в файл jar Scala и получить к ним доступ в R. Конечной целью является создание способа доступа к определенным и часто используемым таблицам базы данных в Python, R и Scala, не создавая для каждой другой библиотеки.Использование SparkR JVM для вызова методов из файла jar Scala
Чтобы сделать это, я сделал файл jar в Scala с функциями, которые используют библиотеку SparkSQL для запроса базы данных и получения требуемых DataFrames. Я хотел иметь возможность называть эти функции в R без создания другой JVM, поскольку Spark уже работает на JVM в R. Однако использование JVM Spark не отображается в SparkR API. Чтобы сделать его доступным и сделать Java-методы вызываемыми, я изменил «backend.R», «generics.R», «DataFrame.R» и «NAMESPACE» в пакете SparkR и перестроил пакет:
В «backend» .R»Я сделал„callJMethod“и„createJObject“формальные методы:
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>", ...)
})
Я изменил„generics.R“также содержат эти функции:
#' @rdname callJMethod
#' @export
setGeneric("callJMethod", function(objId, methodName, ...) { standardGeneric("callJMethod")})
#' @rdname newJobject
#' @export
setGeneric("newJObject", function(className, ...) {standardGeneric("newJObject")})
Затем я добавил экспорта для этих функций файл NAMESPACE:
export("cacheTable",
"clearCache",
"createDataFrame",
"createExternalTable",
"dropTempTable",
"jsonFile",
"loadDF",
"parquetFile",
"read.df",
"sql",
"table",
"tableNames",
"tables",
"uncacheTable",
"callJMethod",
"newJObject")
Это позволило мне назвать функции Scala, которые я написал, не запустив новую JVM.
Методы scala, которые я написал, возвращают DataFrames, которые являются «jobj» s в R при возврате, но SparkR DataFrame - это среда + jobj. Чтобы превратить эти данные DataFrames в SparkR DataFrames, я использовал функцию dataFrame() в «DataFrame.R», которую я также сделал доступной, следуя приведенным выше шагам.
Тогда я смог получить доступ к DataFrame, который я «построил» в Scala из R, и использовать все функции SparkR на этом DataFrame. Мне было интересно, есть ли лучший способ сделать такую кросс-язычную библиотеку, или если есть какая-то причина, что Spark JVM не должен быть общедоступным?
Но есть ли хороший способ обмена данными по R и Scala без необходимости хранить данные и повторно читать их обратно? Если мне не хватает чего-то решения 2 и 3, похоже, это требует. – shj
Я не совсем уверен, чего вы хотите. Spark не поддерживает ни несколько контекстов на JVM (см. [SPARK-2243] (https://issues.apache.org/jira/browse/SPARK-2243)), ни обмен RDD между контекстами. Таким образом, все три требуют чтения данных из определенного типа хранилища. Там есть некоторые опции, такие как [spark-jobserver] (https://github.com/spark-jobserver/spark-jobserver), [«общие» RDD] (https://ignite.apache.org/features/igniterdd. html) поверх Ignite или используя [Tachyon] (http://tachyon-project.org/) как слой с памятью, который пытается решить эту проблему, но простая демонстрация JVM нигде не приведет вас. – zero323
Для простых SQL-запросов вы, вероятно, можете использовать buit-in [Thrift server] (http://spark.apache.org/docs/latest/sql-programming-guide.html#running-the-thrift-jdbcodbc-server). – zero323