作业

作业是在 Azure Databricks 群集中运行非交互式代码的一种方式。 例如,可以采用交互方式或按计划运行提取、转换和加载 (ETL) 工作负载。 你还可以在笔记本 UI 中以交互方式运行作业。

可以通过 UI、CLI 以及调用作业 API 来创建和运行作业。 可以使用 UI、CLI、API 和电子邮件警报监视作业运行结果。 本文重点介绍如何使用 UI 执行作业任务。 有关其他方法,请参阅作业 CLI和作业API 2.1。

可以在工作区 中启用 多个任务的Azure Databricks业务流程。 启用任务业务流程后,作业可以包含一个或多个任务,Azure Databricks管理该作业的任务业务流程、群集管理、监视和错误报告。 在未启用任务业务流程的工作区中,作业由单个任务组成。 Databricks 建议启用任务业务流程,以简化数据和机器学习工作流的创建、管理和监视。 有关 启用 任务业务流程的信息,请参阅要求。

可以在 Azure Databricks 笔记本、增量实时表管道或以 Scala、Java 或 Python 编写的应用程序中实现任务。 还支持旧式 Spark Submit 应用程序。

启用多个任务的业务流程时,通过指定任务之间的依赖关系来控制任务的执行顺序。 可将任务配置为按顺序或并行运行。 下图演示了一个工作流,该工作流:

  1. 引入原始点击流数据,并执行处理以将记录会话化。

  2. 引入顺序数据,并将其与会话化的点击流数据相联接,以准备好要分析的数据集。

  3. 从准备好的数据中提取特征。

  4. 并行执行任务,以持久保存特征并训练机器学习模型。

    多任务工作流示例

若要创建第一个协调多个任务的作业,请参阅 作业快速入门

重要

  • 只能在数据科学工程工作区或数据科学工作区内 & 创建机器学习作业。
  • 工作区限制于 1000 个并发作业运行。 请求 429 Too Many Requests 无法立即启动的运行时,将返回响应。
  • 工作区在一小时内可以创建的作业数限制为 5000(包括“立即运行”和“运行提交”)。 此限制还会影响 REST API 和笔记本工作流创建的作业。

要求

若要创建协调多个任务的作业,管理员必须在 Databricks 管理控制台 中启用支持

创建作业

  1. 执行下列操作之一:

    • 单击 侧栏中的"作业 "图标"作业",然后单击" 创建作业
    • 在侧栏中,单击创建",然后从菜单中选择"作业"。

    如果 启用了 多个任务的业务流程,则"任务"选项卡将随"创建任务"对话框一起显示。 如果未 启用 任务业务流程,"任务"选项卡将随"创建任务"对话框一起显示。

  2. "添加作业名称..." 替换为作业名称。

  3. 如果启用了多个任务的业务流程,请在"任务名称"字段中输入 任务 的名称。

  4. 指定要运行的任务的类型。 在"类型"下拉列表中,选择"笔记本"、JAR、"Spark提交"、Python或"管道"。

    • 笔记本:使用文件资源管理器找到笔记本,单击笔记本名称,然后单击“确认” 。

    • JAR:指定“Main 类” 。 使用包含 main 方法的类的完全限定名称,例如 org.apache.spark.examples.SparkPi。 然后单击“依赖库”下的“添加”以添加运行任务所需的库 。 其中一个库必须包含 main 类。

      若要详细了解 JAR 任务,请参阅 JAR 作业

    • Spark Submit:在“参数”文本框中,以 JSON 字符串数组格式指定 main 类、库 JAR 的路径以及所有参数 。 以下示例将某个 spark-submit 任务配置为运行 Apache Spark 示例中的 DFSReadWriteTest

      ["--class","org.apache.spark.examples.DFSReadWriteTest","dbfs:/FileStore/libraries/spark_examples_2_12_3_1_1.jar","/dbfs/databricks-datasets/README.md","/FileStore/examples/output/"]
      

      重要

      spark-submit 任务有几个限制:

      • 只能在新群集上运行 spark-submit 任务。
      • Spark-submit 不支持群集自动缩放。 若要详细了解自动缩放,请参阅群集自动缩放
      • Spark-submit 不支持 Databricks 实用程序。 若要使用 Databricks 实用程序,请改用 JAR 任务。
    • Python:在" 路径" 文本框中,在 DBFS 或云存储上输入 Python 脚本的 URI;例如,

    • 管道:在 "管道 "下拉列表中,选择现有的 Delta Live Tables 管道。

    • Python Wheel:在" 包名称 "文本框中,输入要导入的包,例如 。 在 "入口点" 文本框中,输入启动滚轮时要调用的函数。 单击"依赖库"下的"添加",添加运行任务所需的库。

  5. 配置运行任务的群集。 在"群集"下拉列表中,选择"新建作业群集"或"现有All-Purpose群集"。

    • 新作业群集:单击“群集”下拉列表中的“编辑”,并完成群集配置
    • 现有的通用群集:在“群集”下拉列表中选择现有群集。 若要在新页面中打开群集,请单击群集名称和说明右侧"外部链接"图标。

    若要详细了解如何选择和配置群集以运行任务,请参阅群集配置提示

  6. 可以传递任务的参数。 每种任务类型在参数格式设置和传递参数方面具有不同的要求。

    • 笔记本:单击“添加”,然后指定要传递给任务的每个参数的键和值 。 使用"使用不同的参数运行作业"选项手动运行任务时,可以重写或 添加其他 参数。 参数设置由参数的键指定的笔记本小组件的值。 使用任务参数变量将有限的一组动态值作为参数值的一部分传递。
    • JAR:使用 JSON 格式的字符串数组指定参数。 这些字符串作为参数传递给 main 类的 main 方法。 请参阅 配置 JAR 作业参数
    • Spark Submit 任务:以 JSON 格式字符串数组的形式指定参数。 依据 Apache Spark spark-submit 约定,将 JAR 路径后的参数传递给 main 类的 main 方法。
    • Python:使用 JSON 格式的字符串数组指定参数。 这些字符串将作为参数传递,可以使用 Python 中的 argparse 模块分析这些参数。
    • Python Wheel:"参数"下拉列表中,选择"参数" (字符串数组) 以输入参数作为 JSON 格式的字符串数组,或选择"kwargs (键值对) "以输入每个参数的键和值。
  7. 若要访问其他选项(包括“依赖库”、“重试策略”和“超时”),请单击“高级选项” 。 请参阅 编辑任务

  8. 单击“创建”。

  9. 若要选择性地设置作业的计划,请单击 "作业详细信息 "面板中的" 编辑计划 "。 请参阅计划作业

  10. 若要选择性地允许同一作业的多个并发运行,请单击"作业详细信息"面板 中的 "编辑 并发运行 "。 请参阅最大并发运行数

  11. 若要选择性地指定接收作业事件警报的电子邮件地址,请单击"作业详细信息"面板中的"编辑警报"。 请参阅警报

  12. 若要选择性地控制作业的权限级别,请单击"作业 详细信息 "面板中的" 编辑权限 "。 请参阅 控制对作业 的访问

若要在启用任务业务流程时添加另一个任务,请单击刚创建的任务下方的"添加任务按钮"。

运行作业

  1. 单击 侧栏中的"作业 "图标"作业"。
  2. 选择一个作业,然后单击“运行”选项卡。可以立即运行作业,也可以计划稍后运行作业。

立即运行作业

若要立即运行作业,请单击 " 立即运行

提示

可以通过单击“立即运行”来使用笔记本任务执行作业的测试运行。 如果需要对笔记本进行更改,在编辑笔记本后再次单击“立即运行”将自动运行新版本的笔记本。

使用不同参数运行作业

可以使用“立即使用不同参数运行”选项,以便使用不同参数或现有参数的不同值重新运行作业。

  1. 单击 "立即运行" 旁边蓝色向下插入符号,选择 "立即运行",然后选择 "在活动运行" 表中,单击 "立即运行",并选择不同的参数。 根据任务的类型输入新参数。
    • 笔记本:可以输入参数作为键/值对或 JSON 对象。 可以使用此对话框设置小组件的值。
    • JAR 和 spark-submit:可以输入参数列表或 JSON 文档。 提供的参数会与已触发的运行的默认参数合并。 如果删除键,则会使用默认参数。 还可为运行添加任务参数变量
  2. 单击 “运行”

计划作业

若要定义作业的计划,请执行以下操作:

  1. 在 "作业详细信息" 面板中单击 "编辑计划",并将计划类型设置为 "已计划"。

  2. 指定时间段、开始时间和时区。 (可选)选中“显示 Cron 语法”复选框以使用 Quartz Cron 语法显示和编辑计划。

    注意

    • Azure Databricks 强制实施在作业计划触发的后续运行之间的最小间隔(10 秒),而不考虑 cron 表达式中的秒配置。
    • 可以选择一个采用夏令时或 UTC 时间的时区。 如果选择一个采用夏令时的区域,则在夏令时开始或结束时,某个每小时作业可能会被系统跳过,或者会在一到两个小时内显示为未触发。 若要每小时(绝对时间)运行作业,请选择“UTC”。
    • 作业计划程序不适用于低延迟作业。 由于网络或云问题,作业运行的延迟时间有时可能会长达数分钟。 在这些情况下,计划的作业会在服务可用后立即运行。
  3. 单击“保存” 。

暂停和恢复作业计划

若要暂停作业,可以执行以下任一操作:

  • 在 "作业详细信息" 面板中单击 "暂停"。
  • 在 "作业详细信息" 面板中单击 "编辑计划",并将 "计划类型" 设置为 "手动 (暂停)

若要恢复暂停的作业计划,请将 计划类型 设置为 "已 计划"。

查看作业

单击侧栏中的 " 作业作业 。 此时将显示 "作业" 列表。 "作业" 页将列出所有定义的作业、群集定义、计划(如果有)以及上次运行的结果。

可以在“作业”列表中筛选作业:

  • 使用关键字。
  • 仅选择你拥有的作业。
  • 选择你有权访问的所有作业。 访问此筛选器需要启用作业访问控制

你还可以单击任何列标题,以便按该列对作业列表排序(降序或升序)。 默认按作业名称升序排序。

查看作业运行

  1. 单击侧栏中的 " 作业作业
  2. 在“名称”列中单击作业名称。 “运行”选项卡显示活动运行和已完成的运行。

作业详细信息

Azure Databricks 最多可以保留 60 天的作业运行历史。 如果需要保留作业运行,Databricks 建议在结果过期之前将其导出。 有关详细信息,请参阅导出作业运行结果

查看作业运行详细信息

作业运行详细信息页包含作业输出和日志链接。 当启用多个任务的业务流程时,"作业运行详细信息" 页包含有关作业运行中每个任务的成功或失败的信息。 可以通过作业的“运行”选项卡访问作业运行详细信息。 若要在 " 运行 " 选项卡中查看作业运行详细信息,请在 "已完成运行的运行 " 列中单击 "运行" 的链接, (过去60天) 表。 若要返回到作业的 " 运行 " 选项卡,请单击 作业 ID 值。

对于协调多个任务的作业,单击任务查看任务运行详细信息,包括:

  • 运行该任务的群集
    • 该任务的 Spark UI
    • 该任务的日志
    • 该任务的指标

单击 " 作业 ID " 值,返回到该作业的 " 运行 " 选项卡。 单击 " 作业运行 ID " 值,返回到作业运行详细信息。

导出作业运行结果

可以为所有作业类型导出笔记本运行结果和作业运行日志。

导出笔记本运行结果

可以通过导出作业运行的结果来持久保存作业运行。 对于笔记本作业运行,可以先导出呈现的笔记本,稍后再将其导入到 Azure Databricks 工作区中。

使用单个任务导出作业的笔记本运行结果:

  1. 在 "作业详细信息" 页上,单击 " 查看详细信息 " 链接,以在 "已完成运行" 的 " 运行 时间" 列中, (过去60天) 表中运行。
  2. 单击“导出到 HTML”。

为包含多个任务的作业导出笔记本运行结果:

  1. 在 "作业详细信息" 页上,单击 " 查看详细信息 " 链接,以在 "已完成运行" 的 " 运行 时间" 列中, (过去60天) 表中运行。
  2. 单击用于导出的笔记本任务。
  3. 单击“导出到 HTML”。

导出作业运行日志

你还可以导出作业运行的日志。 可以设置作业,通过作业 API 自动将日志传递到 DBFS。 查看 new_cluster.cluster_log_conf 请求正文中的对象,该对象传递到 (在作业 API 中) 的 " new_cluster.cluster_log_conf 操作" POST /jobs/create

编辑作业

作业中提供了一些配置选项,而其他选项可用于各个 任务。 例如,只能对作业设置最大并发运行,而必须为每个任务定义参数。

若要更改作业的配置,请执行以下操作:

  1. 单击侧栏中的 " 作业作业
  2. 在“名称”列中单击作业名称。

边侧面板将显示“作业详细信息”。 你可以更改 计划、群集配置、警报和并发运行的最大数目。 如果启用了 " 作业访问控制 ",则还可以编辑作业权限。

最大并发运行数

此作业的最大并行运行数。 尝试启动新的运行时,如果作业已达到其最大活动运行数,Azure Databricks 会跳过该运行。 若要以并发方式执行同一作业的多个运行,请将此值设置为高于默认值 1。 设置此值适用于这样的情形:例如,如果你按计划频繁触发作业并希望允许连续的运行彼此重叠,或者,如果你希望触发多个在输入参数方面有区别的运行。

警报

你可以添加一个或多个电子邮件地址,以在该作业的运行开始、完成或失败时通知:

  1. 单击 " 编辑警报"。
  2. 单击 添加
  3. 输入要通知的电子邮件地址,然后单击每个警报类型要发送到该地址的复选框。
  4. 若要输入其他通知的电子邮件地址,请单击 " 添加"。
  5. 如果你不想接收有关已跳过的作业运行的警报,请单击该复选框。
  6. 单击“确认” 。

配置电子邮件警报

将这些电子邮件警报与你最喜欢的通知工具集成,这些工具包括:

控制对作业的访问

作业所有者和管理员可以通过作业访问控制授予对其作业的精细权限。 作业所有者可以选择允许哪些其他用户或组查看作业的结果。 所有者还可以选择允许谁管理其作业运行(“立即运行”和“取消运行”权限)。

有关详细信息,请参阅作业访问控制

编辑任务

设置任务配置选项:

  1. 单击侧栏中的 " 作业作业
  2. 在“名称”列中单击作业名称。
  3. 当启用了多个任务的业务流程时,请单击 " 任务 " 选项卡。如果未启用任务业务流程,请单击 " 任务 " 选项卡。

任务依赖关系

如果启用了多个任务的业务流程,则可以使用 " 依赖于 " 下拉箭头来定义作业中任务的执行顺序。 可将此字段设置为作业中的一个或多个任务。

编辑任务依赖项

注意

如果作业仅包括一个任务,则“依赖于”将不可见。

配置任务依赖关系会创建任务执行的有向无环图 (DAG)。DAG 是在作业计划程序中表示执行顺序的常用方式。 以下面包括四个任务的作业为例:

任务依赖关系示例关系图

  • 任务 1 是根任务,不依赖于任何其他任务。
  • 任务 2 和任务 3 依赖于任务 1 首先完成。
  • 最后,任务 4 依赖于任务 2 和任务 3 成功完成。

Azure Databricks 在运行下游任务之前运行上游任务,并且会并行运行尽可能多的这些任务。 以下示意图演示了这些任务的处理顺序:

任务依赖关系示例流

单个任务配置选项

各个任务具有以下配置选项:

本节内容:

群集

若要配置运行任务的群集,请单击 " 群集 " 下拉箭头。 若要详细了解如何选择和配置群集以运行任务,请参阅群集配置提示

注意

每个任务要么在通用群集中运行,要么在新的作业群集中运行。 不能将同一作业群集用于作业中的多个任务。

依赖库

依赖库将在该任务运行之前安装在群集上。 必须设置所有任务依赖项,以确保在运行开始之前已安装它们。

若要添加依赖库,请单击“高级选项”,然后选择“添加依赖库”打开“添加依赖库”选择器 。 请按照库依赖项中的建议来指定依赖项。

重要

如果已将库配置为 自动在所有群集上安装,或者选择已安装库的现有已终止群集,则作业执行不会等待库安装完成。 如果作业需要某个库,则应在“依赖库”字段中将该库附加到此作业。

任务参数变量

可以将模板化变量作为任务参数的一部分传递到作业任务。 当作业任务运行时,这些变量将替换为相应的值。 可以使用任务参数值来传递有关作业运行的上下文,例如运行 ID 或作业的开始时间。

运行作业时,将替换由双花括号括起来的任务参数变量,并将其追加到作为值的一部分包含的可选字符串值。 例如,要为作业 ID 6 的任何运行传递名为 MyJobId 且值为 my-job-6 的参数,请添加以下任务参数:

{
  "MyJobID": "my-job-{{job_id}}"
}

双大括号的内容不会计算为表达式,因此不能在双花括号内执行运算或函数。 不会在大括号内去除空格,因此不会对 {{ job_id }} 进行计算。

支持以下任务参数变量:

变量 说明
{{job_id}} 分配给作业的唯一标识符
{{run_id}} 分配给作业运行的唯一标识符
{{start_date}} 作业运行的开始日期。 格式为 UTC 时区的 yyyy-MM-dd。
{{start_time}} 创建并准备好群集后运行开始执行的时间戳。 格式为 UTC 时区自 UNIX 纪元以来的毫秒数,如 System.currentTimeMillis() 所返回。
{{task_retry_count}} 第一次尝试运行任务失败后的重试次数。 第一次尝试时的值为 0,每次重试时值会递增。

启用多个任务的业务流程时,支持以下任务参数变量:

变量 说明 示例值
{{parent_run_id}} 分配给包含多个任务的作业运行的唯一标识符。 3447835
{{task_key}} 分配给包含多个任务的作业一部分的任务的唯一名称。 "clean_raw_data"

创建作业编辑作业使用不同参数运行作业时,可以为任何任务设置这些变量。

超时

作业的最长完成时间。 如果作业未在此时间内完成,则 Azure Databricks 会将其状态设置为“已超时”。

重试

一项策略,用于确定重试已失败运行的时间和次数。 若要为任务设置重试,请单击“高级选项”并选择“编辑重试策略” 。

注意

如果同时配置“超时”和“重试”,则超时将应用于每次重试。

克隆作业

可以通过克隆现有作业来快速创建新作业。 克隆某个作业会创建与该作业相同的副本,只有作业 ID 不同。 在作业页上,单击该作业名称旁边的 " 更多 ... ",并从下拉菜单中选择 " 克隆 "。

克隆任务

可以通过克隆现有任务来快速创建新任务:

  1. 在作业页上,单击 " 任务 " 选项卡。
  2. 选择要克隆的任务。
  3. 单击 " 作业 ,然后选择 " 克隆任务"。

删除作业

若要删除作业,请在作业的页上,单击该作业名称旁边的 " 更多 ... ",并从下拉菜单中选择 " 删除 "。

删除任务

若要在启用多个任务的业务流程时删除任务:

  1. 单击 " 任务 " 选项卡。
  2. 选择要删除的任务。
  3. 单击 " 作业垂直省略号 " 并选择 " 删除任务"。

复制任务路径

若要复制任务的路径,例如,笔记本路径:

  1. 单击 " 任务 " 选项卡。
  2. 选择包含要复制的路径的任务。
  3. 单击任务路径旁边的 " 作业复制 ,将路径复制到剪贴板。

最佳实践

本节内容:

群集配置提示

将作业操作化时,群集配置非常重要。 以下内容提供有关选择和配置作业群集的常规指导,并提供针对特定作业类型的建议。

为作业选择适当的群集类型

  • 新作业群集 是在运行任务时创建和启动的专用群集,并且在任务完成后立即终止。 在生产环境中,Databricks 建议使用新群集,使每个任务在完全隔离的环境中运行。
  • 在新群集上运行某个任务时,该任务被视为数据工程(任务)工作负载,受任务工作负载定价的约束。 在现有通用群集上运行某个任务时,该任务被视为数据分析(通用)工作负载,受通用工作负载定价的约束。
  • 如果选择终止的现有群集,并且作业所有者 可以重新启动权限,则在计划运行该作业时,Azure Databricks 会启动该群集。
  • 现有通用群集最适用于按固定时间间隔更新仪表板之类的任务。

使用池缩短群集启动时间

若要缩短新作业群集开始时间,请创建一个,并将该作业的群集配置为使用该池。

笔记本作业提示

笔记本单元格输出总计(所有笔记本单元格的合并输出)存在 20MB 的大小限制。 此外,单个单元格输出存在 8MB 的大小限制。 如果单元格输出大小总计超出 20MB,或者单个单元格的输出大于 8MB,则会取消该运行并将其标记为失败。

如果需要帮助查找超出限制的单元格,请针对所有用途的群集运行该笔记本,并使用此 笔记本自动保存技术

流式处理任务

Spark 流式处理作业的最大并发运行数不得设置为大于 1。 流式处理作业应该设置为使用 cron 表达式 "* * * * * ?" 每分钟 (运行一次) 。

由于流式处理任务持续运行,因此它始终应是作业中的最后一个任务。

JAR 作业

在运行 JAR 作业时,请注意以下事项:

输出大小限制

注意

适用于 Databricks Runtime 6.3 及更高版本。

作业输出(如发送到 stdout 的日志输出)的大小限制为 20MB。 如果总输出更大,将取消运行并将其标记为失败。

若要避免遇到此限制,可以通过将 spark.databricks.driver.disableScalaOutput Spark 配置设置为 true 来阻止 stdout 从驱动程序返回到 Azure Databricks。 默认情况下,标志值为 false 。 该标志控制 Scala JAR 作业和 Scala 笔记本的单元格输出。 如果启用该标志,Spark 不会将作业执行结果返回给客户端。 该标志不影响写入群集日志文件中的数据。 建议将此标志设置为仅用于 JAR 作业的作业群集,因为它将禁用笔记本结果。

使用共享的 SparkContext

因为 Azure Databricks 是托管服务,所以可能需要进行一些代码更改,以确保 Apache Spark 作业正常运行。 JAR 作业程序必须使用共享 SparkContext API 来获取 SparkContext。 由于 Azure Databricks 初始化 SparkContext,因此调用 new SparkContext() 的程序会失败。 若要获取 SparkContext,请只使用由 Azure Databricks 创建的共享 SparkContext

val goodSparkContext = SparkContext.getOrCreate()
val goodSparkSession = SparkSession.builder().getOrCreate()

在使用共享 SparkContext 时,还应避免使用几种方法。

  • 不要调用 SparkContext.stop()
  • 请勿在 Main 程序的末尾调用 System.exit(0)sc.stop()。 这可能会导致未定义的行为。

使用 try-finally 块进行作业清理

假设有一个由两部分组成的 JAR:

  • jobBody(),包含作业的主要部分。
  • jobCleanup() 必须在 jobBody() 后执行,不管该函数是成功还是返回了异常。

例如,jobBody() 可以创建表,你可以使用 jobCleanup() 来删除这些表。

若要确保调用清理方法,安全的方法是在代码中放置一个 try-finally 块:

try {
  jobBody()
} finally {
  jobCleanup()
}

不应尝试使用 或以下代码进行清理:

val cleanupThread = new Thread { override def run = jobCleanup() }
Runtime.getRuntime.addShutdownHook(cleanupThread)

考虑到 Spark 容器的生存期在 Azure Databricks 中的管理方式,ShutdownHook 的运行并不可靠。

配置 JAR 作业参数

使用 JSON 字符串数组将参数传递给 JAR 作业。 查看 spark_jar_task 请求正文中的对象,该对象传递到 (在作业 API 中) 的 " spark_jar_task 操作" POST /jobs/create 。 若要访问这些参数,请检查传入到 main 函数中的 String 数组。

库依赖项

Spark 驱动程序的某些库依赖项不能重写。 这些库优先于与它们冲突的任何库。

若要获取驱动程序库依赖项的完整列表,请在附加到同一 Spark 版本的群集(或包含要检查的驱动程序的群集)的笔记本中运行以下命令。

%sh
ls /databricks/jars

管理库依赖项

如果在为作业创建 JAR 时处理库依赖项,则最好是将 Spark 和 Hadoop 作为 provided 依赖项列出。 在 Maven 上,将 Spark 和 Hadoop 添加为提供的依赖项,如以下示例中所示:

<dependency>
  <groupId>org.apache.spark</groupId>
  <artifactId>spark-core_2.11</artifactId>
  <version>2.3.0</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.apache.hadoop</groupId>
  <artifactId>hadoop-core</artifactId>
  <version>1.2.1</version>
  <scope>provided</scope>
</dependency>

在中 sbt ,将 Spark 和 Hadoop 添加为提供的依赖项,如以下示例中所示:

libraryDependencies += "org.apache.spark" %% "spark-core" % "2.3.0" % "provided"
libraryDependencies += "org.apache.hadoop" %% "hadoop-core" % "1.2.1" % "provided"

提示

为依赖项指定正确的 Scala 版本,具体取决于你所运行的版本。