Google cloud storage PySpark&x2B;谷歌云存储(wholeTextFiles)

Google cloud storage PySpark&x2B;谷歌云存储(wholeTextFiles),google-cloud-storage,google-compute-engine,pyspark,google-cloud-dataproc,Google Cloud Storage,Google Compute Engine,Pyspark,Google Cloud Dataproc,我正在尝试使用PySpark(googledataproc)解析大约100万个HTML文件,并将相关字段写入压缩文件。每个HTML文件大约200KB。因此,所有数据约为200GB 如果我使用数据的一个子集,下面的代码可以正常工作,但在整个数据集上运行时会运行数小时,然后崩溃。此外,没有使用工作节点(来回答您的问题主节点不会读取所有包含的数据,但它会在开始工作之前获取所有输入文件的状态。Dataproc设置属性“mapreduce.input.fileinputformat.list status

我正在尝试使用PySpark(googledataproc)解析大约100万个HTML文件,并将相关字段写入压缩文件。每个HTML文件大约200KB。因此,所有数据约为200GB


如果我使用数据的一个子集,下面的代码可以正常工作,但在整个数据集上运行时会运行数小时,然后崩溃。此外,没有使用工作节点(来回答您的问题主节点不会读取所有包含的数据,但它会在开始工作之前获取所有输入文件的状态。Dataproc设置属性“mapreduce.input.fileinputformat.list status.num threads”默认设置为20,以帮助缩短此查找的时间,但在GCS中仍会对每个文件执行RPC

您似乎发现了这样一种情况,即即使添加线程也没有多大帮助,只会使驱动程序更快

关于如何并行阅读,我有两个想法

但首先,有一点警告:这两种解决方案都不是非常健壮的,因为它们对包含在glob中的目录都非常健壮。您可能希望防止目录出现在要读取的文件列表中

第一个是用python和hadoop命令行工具完成的(这也可以用gsutil完成)。下面是一个示例,说明它如何在Worker上查看和执行文件列表,将文件内容成对读取,最后计算成对(文件名、文件长度):

from\uuuuu future\uuuuu导入打印功能
从pyspark.rdd导入rdd
从pyspark导入SparkContext
导入系统
导入子流程
def hadoop(文件全局):
lines=子进程。检查输出([“/usr/bin/hadoop”,“fs”,“-ls”,file\u glob])。拆分(“\n”)
如果len(line)>0,则files=[line.split()[7]用于行中的行
返回文件
def hadoop_目录(文件):
返回子进程。检查_输出([“/usr/bin/hadoop”,“fs”,“-cat”,file])。解码(“utf-8”)
如果名称=“\uuuuu main\uuuuuuuu”:
如果len(系统argv)<2:
打印(“提供要读取的路径全局列表”)
出口(-1)
sc=SparkContext()
#这只是为了测试。您需要生成一个列表
#的前缀globs,而不是从
#命令行。
globs=sys.argv[1:]
#所需的列表分区计数
lpc=100
#所需的“cat”分区计数应小于文件总数
cpc=1000
files=sc.parallelize(globs).repartition(lpc).flatMap(hadoop\u ls)
files_和_content=files.repartition(cpc.map)(lambda f:[f,hadoop_cat(f)])
files_and_char_count=files_and_content.map(lambda p:[p[0],len(p[1]))
local=files\u和\u char\u count.collect()
对于本地配对:
打印(“文件{}有{}个字符”。格式(对[0],对[1]))
我将首先从这个子流程解决方案开始,研究hadoop_ls和hadoop_cat调用的分区,看看您是否可以得到可以接受的东西

第二种解决方案更为复杂,但可能会通过避免许多exec调用而产生性能更高的管道

在第二个解决方案中,我们将编译一个特殊用途的helperjar,使用初始化操作将该jar复制到所有工作人员,并最终使用驱动程序中的helper

scala jar项目的最终目录结构如下所示:

helper/src/main/scala/com/google/cloud/dataproc/support/PysparkHelper.scala
helper/build.sbt
在PysparkHelper.scala文件中,我们将有一个小型scala类,它的功能与上述纯python解决方案类似。首先,我们将创建文件全局的RDD,然后创建文件名的RDD,最后创建文件名和文件内容对的RDD

package com.google.cloud.dataproc.support
导入collection.JavaConversions_
导入org.apache.commons.io.IOUtils
导入org.apache.hadoop.conf.Configuration
导入org.apache.hadoop.fs.{文件系统,路径}
导入org.apache.spark.api.java.{javapairdd,JavaSparkContext}
导入java.util.ArrayList
导入java.nio.charset.StandardCharset
类PysparkHelper扩展了Serializable{
def wholeTextFiles(
上下文:JavaSparkContext,
路径:ArrayList[String],
分区:Int):javapairdd[String,String]={
val globRDD=context.sc.parallelize(路径).重新分区(分区)
//将全局映射到文件名:
val filenameRDD=globRDD.flatMap(glob=>{
val路径=新路径(全局)
val fs:FileSystem=path.getFileSystem(新配置)
val状态=fs.globStatus(路径)
statuses.map(s=>s.getPath.toString)
})
//将文件名映射到(名称、内容)对:
//todo:考虑添加第二个PARIITON计数参数来重新分区之前
//下面是地图。
val fileNameContentRDD=filenameRDD.map(f=>{
对(f,读取路径(f,新配置))
})
新的JavaPairRDD(fileNameContentRDD)
}
def readPath(文件:字符串,配置)={
val path=新路径(文件)
val fs:FileSystem=path.getFileSystem(conf)
val stream=fs.open(路径)
试一试{
IOUtils.toString(流,标准字符集.UTF_8)
}最后{
stream.close()
}
}
}
helper/build.sbt文件如下所示:

helper/src/main/scala/com/google/cloud/dataproc/support/PysparkHelper.scala
helper/build.sbt
组织:=“com.google.cloud.dataproc.support”
名称:=“pyspark_支持”
版本:=“0.1”
规模规避:=“2.10.5”
libraryDependencies+=“org.apache.spark”%”spark-core_2.10“%”1.6.0“%”已提供
libraryDependencies+=“org.apache.hadoop”%”hadoop通用“%”2.7.1“%”提供
exportJars:=true
然后,我们可以使用sbt构建帮助器:

$ cd helper && sbt package
输出助手jar应该是target/scala-2.10/pyspark\u support\u 2.10-0.1.jar

我们现在需要将这个jar放到集群上,为此,我们需要做两件事:1)将jar上传到GCS,2)在GCS中创建一个初始化操作,将jar复制到集群节点

为了便于说明,让我们假设您的bucket名为MY_bucket(在此处插入与海象相关的适当meme)

创建一个初始化操作(我们称之为pyspark_init_action.sh,将我的_BUCKET替换为
$ gsutil cp target/scala-2.10/pyspark_support_2.10-0.1.jar gs://MY_BUCKET/pyspark_support.jar
#!/bin/bash

gsutil cp gs://MY_BUCKET/pyspark_support.jar /usr/lib/hadoop/lib/
$ gsutil cp pyspark_init_action.sh gs://MY_BUCKET/pyspark_init_action.sh
--initialization-actions gs://MY_BUCKET/pyspark_init_action.sh