我使用Spark Dataframe API从NFS Share加载/读取文件,然后将该文件的数据保存/写入HDFS。
我有一个三节点Spark Cluster,一个主节点和两个Worker节点。我的Spark Cluster使用YARN作为Cluster Manager,因此两个Worker节点是YARN NodeManager节点,主节点是Yarn ResourceManager节点。
我有一个远程位置说/ data / files安装到所有三个YARN / SPARK节点,因为它是[/ data / files]所有csv文件[多个]都存在,我想读从最后写到HDFS。
我在主节点上运行以下代码
import java.io.File
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.DataFrame
import org.apache.spark.sql.SQLContext
object TestMoreThan1CSV2DF {
private val source: String = "file:///data/files/"
private val destination = "hdfs://<myHostIP>:8020/raw/"
private val fileFormat : String = "com.databricks.spark.csv"
def main(args:Array[String]):Unit={
val conf = new SparkConf().setAppName("TestMoreThan1CSV2DF").setMaster("local")
val sc = new SparkContext(conf)
val sqlContext = new SQLContext(sc)
val fileArray: Array[File] = new java.io.File(source).listFiles.filter(_.getName.endsWith(".csv"))
for(file<-fileArray){
// reading csv file from shared location and taking whole data in a dataframe
var df = loadCSV2DF(sqlContext, fileFormat, "true", "true", file.getName)
// variable for holding destination location : HDFS Location
var finalDestination: String = destination+file.getName
// saving data into HDFS
writeDF2HDFS(df,fileFormat,"true",finalDestination) /// saved using default number of partition = 1
}
}
def loadCSV2DF(sqlContext : SQLContext, fileFormat: String, header : String, inferSchema: String, source: String) : DataFrame = {
try{
sqlContext.read.format(fileFormat)
.option("header", header) // Use first line of all files as header
.option("inferSchema", inferSchema) // Automatically infer data types
.load(source)
}
catch{
case ex: OnboardingException => {
throw ex;
}
}
}
def writeDF2HDFS(df: DataFrame, fileFormat: String, header: String, destination: String, partitions: Integer = 1){
try{
df.repartition(partitions).write.format(fileFormat).option("header",header).save(destination)
}
catch{
Case ez : OnboardingException => {
throw ez;
}
}
}
}
此代码读取共享位置中存在的所有csv文件 / data / files /并将其中的每一个写入HDFS。例如: /data/files/f1.csv将作为/raw/f1.csv/part-xxxxx加载到HDFS中 文件
在运行此代码时,我无法理解:
1)整个代码在哪里运行?它是否在驱动程序上运行?或使用 两个工人?
2)load()和save()API是否在工作节点上运行 它并行工作?如果是,那么两名工人如何跟踪 它读过或写过的那段时间?
3)截至目前我是 在“for”循环中按顺序读取每个文件并处理每个文件 它们是顺序的,是否可以使它成为多线程 应用程序,其中每个文件分配给一个线程进行执行 端到端读写并行。磁盘IO是否会受到任何约束 这样做的时候?
任何快速回复/参考/指针都将不胜感激。
此致 布佩希
答案 0 :(得分:1)
从我的查询的另一个线程复制的非常好的解释: differentiate driver code and work code in Apache Spark
在此处复制部分内容: 由转换创建的闭包内发生的一切都发生在一个工人身上。这意味着如果在map(...),filter(...),mapPartitions(...),groupBy *(...),aggregateBy *(...)中传递了某些内容,则会对worker执行。它包括从持久存储或远程源读取数据。
通常在驱动程序和工作程序上执行count,reduce(...),fold(...)等操作。重型工作由工人并行执行,并且一些最后的步骤,例如减少从工人那里收到的输出,依次在驾驶员身上执行。
其他所有内容,例如触发操作或转换都发生在驱动程序上。特别是它意味着每个需要访问SparkContext的动作。
就我的疑问而言: 1)是的main()方法的一部分在驱动程序上运行,但转换发生在
2)load()和save()在worker上运行,因为我们可以看到加载创建数据帧[它存储在分区的内存中]并保存在hdfs中创建part-xxxx文件,这表明工作人员正在这样做
3)仍在努力实现这一目标,一旦完成就会回答这个问题。
谢谢
答案 1 :(得分:0)
好实验!!。
1)您的代码始终在worker上运行。司机程序只是为了管理工人。
2)是load()和save()API在工作节点上运行。他们按顺序工作。
3)使用多线程应用程序:我还没有尝试过。祝你好运“试一试!!”但是你为什么要把自己置于复杂的境地!! SPARK知道如何处理这种情况。