【问题标题】:StackOverflowError in AWS Glue while reading a million JSON files in Spark在 Spark 中读取一百万个 JSON 文件时,AWS Glue 中出现 StackOverflowError
【发布时间】:2021-08-25 12:21:30
【问题描述】:

如果我们尝试在 Spark 中从 S3 加载超过一百万个 JSON 文件作为 AWS Glue 作业的一部分,则会发生错误

spark_df = spark.read.load(s3_json_path, format='json')

700,000 个文件可以正常工作,但超过 100 万个文件会导致 StackOverflowError。我使用过 Python 3、Glue 2.0、工作类型 G.1X 和 10 个工作人员(使用 G.2X 或更多工作人员来增加容量没有帮助)。堆栈跟踪是

ERROR [main] glue.ProcessLauncher (Logging.scala:logError(70)): Error from Python:Traceback (most recent call last):
  File "/tmp/glue_job.py", line 107, in <module>
    spark_df = spark.read.load(s3_json_path, format='json')
  File "/opt/amazon/spark/python/lib/pyspark.zip/pyspark/sql/readwriter.py", line 166, in load
    return self._df(self._jreader.load(path))
  File "/opt/amazon/spark/python/lib/py4j-0.10.7-src.zip/py4j/java_gateway.py", line 1257, in __call__
    answer, self.gateway_client, self.target_id, self.name)
  File "/opt/amazon/spark/python/lib/pyspark.zip/pyspark/sql/utils.py", line 63, in deco
    return f(*a, **kw)
  File "/opt/amazon/spark/python/lib/py4j-0.10.7-src.zip/py4j/protocol.py", line 328, in get_return_value
    format(target_id, ".", name), value)
py4j.protocol.Py4JJavaError: An error occurred while calling o70.load.
: java.lang.StackOverflowError

作为一个真正的 StackOverflow 错误,它非常适合这个网站。 Spark应该可以加载一百万个文件,问题出在哪里?我必须调整什么设置才能使其正常工作?

【问题讨论】:

  • 请分享您的 spark-submit 命令?
  • spark-submit 命令由 AWS Glue 完成。我使用了一个 Python 脚本,它使用 boto3.client('glue').start_job_run(..) 来启动 Glue 作业。脚本本身由 Terraform 提供,它使用的唯一提交命令是job.commit(),最后是从 Glue 上下文定义作业:-/
  • 你是在集群模式还是本地模式下运行spark?
  • 在 AWS Glue 中。据我了解,它允许“工人”集群对 Spark 进行无服务器执行。默认情况下,worker 数量为 10 docs.aws.amazon.com/glue/latest/dg/add-job.html
  • 您可能想尝试通过设置--conf "spark.executor.extraJavaOptions=-Xss1M" 或类似的方式来增加 Spark 执行器的 Java 堆栈大小。不知道如何用胶水完成:))

标签: python json apache-spark pyspark apache-spark-sql


【解决方案1】:

我还没有找到解决方案,但我设法找到了解决方法。显然 Spark/PySpark 从 S3 读取太多文件时出现问题。许多页面已经解释了how many small files from S3 should not be pulled in Spark。它看起来像big data has a small files problem。我们可以做的解决方法是使用 Boto3 和自定义函数 read multiple JSON files from S3 in parallel

import json
import boto3

# read all JSON filenames from S3 using Boto3 & pagination
s3 = boto3.client('s3')
paginator = s3.get_paginator('list_objects_v2')
pages = paginator.paginate(Bucket=bucket, Prefix=prefix)
file_list = []
for page in pages:
    for obj in page['Contents']:
        file_list.append(obj['Key'])

# it is important to define the S3 client *inside* the function
# because the S3 client is not serialisable
def load_json(key):
    s3_client = boto3.client('s3')
    json_data = s3_client.get_object(Bucket=bucket, Key=key)['Body'].read()
    return json.loads(json_data)

# read the JSON files in parallel by a custom loading function
data = sparkContext.parallelize(file_list).map(load_json)
dataSchema = StructType([StructField("name", StringType(), True),.. ])
spark_df = spark.createDataFrame(data, schema=dataSchema)

【讨论】:

    猜你喜欢
    • 2016-06-12
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 2021-07-14
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多