You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins部署Scala Parquet写入程序报LocalFileSystem类找不到问题

问题根因

报错核心是Jenkins部署后的运行时类路径缺失Hadoop Common模块的对应类,本地运行正常是两个原因导致的假象:

  • 本地IDE/sbt运行时会默认加载所有作用域(包括provided)的依赖,不会遗漏传递依赖
  • Jenkins打包/部署环节要么存在依赖裁剪、类加载隔离,要么是打包插件的合并策略错误丢弃了Hadoop的SPI配置文件,要么是依赖冲突导致hadoop-common包被排除

你之前尝试的修复存在两处明显错误,导致配置完全没生效:

  • 手动设置Hadoop配置时两次都赋值给fs.hdfs.impl,本地文件系统对应的配置键是fs.file.impl
  • 代码里写的getname是笔误,获取类名的正确方法名是getName(首字母大写),这段代码本身就无法正常编译运行
分步解决方案

1. 修正依赖配置,显式引入缺失模块

不要依赖传递依赖引入hadoop-common,在build.sbt里显式声明对应依赖,避免被排除规则过滤:

libraryDependencies ++= Seq(
  "com.github.mjakubowski84" %% "parquet4s-core" % "2.6.0",
  "org.apache.hadoop" % "hadoop-common" % "2.10.2",
  "org.apache.hadoop" % "hadoop-client" % "2.10.2"
)

如果你是用sbt-assembly打胖包部署,必须添加正确的合并策略,否则META-INF/services下的Hadoop SPI服务发现文件会被覆盖,即使类存在也无法被识别加载:

assembly / assemblyMergeStrategy := {
  case PathList("META-INF", xs @ _*) =>
    xs.map(_.toLowerCase) match {
      case "services" :: _ => MergeStrategy.concat
      case ("manifest.mf" :: Nil) | ("index.list" :: Nil) | ("dependencies" :: Nil) => MergeStrategy.discard
      case _ => MergeStrategy.first
    }
  case _ => MergeStrategy.first
}

如果你是打瘦包部署,检查Jenkins的依赖拷贝逻辑,确保所有runtime作用域的依赖都被完整拷贝到服务器的lib目录,不要遗漏hadoop-common相关的jar包。

2. 修正Hadoop配置代码

把错误的配置替换成正确写法,并且主动触发类加载,避免SPI加载失败:

import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.LocalFileSystem
import org.apache.hadoop.hdfs.DistributedFileSystem

// 上下文类加载器设置必须放在所有Hadoop相关类初始化之前
Thread.currentThread().setContextClassLoader(getClass.getClassLoader)

val hadoopConfig = new Configuration()
hadoopConfig.set("fs.hdfs.impl", classOf[DistributedFileSystem].getName)
hadoopConfig.set("fs.file.impl", classOf[LocalFileSystem].getName)
// 主动触发类加载,提前验证类是否存在
classOf[LocalFileSystem]
classOf[DistributedFileSystem]

3. 排查服务器环境冲突

如果改完上述配置还是报错,逐一检查以下场景:

  • 如果服务器本身预装了Hadoop,检查HADOOP_HOME、全局CLASSPATH配置,确认服务器上的Hadoop版本和你依赖的2.10.2版本一致,避免类加载器优先加载了服务器上版本不兼容、不完整的Hadoop包。这种场景建议直接打胖包部署,不要依赖服务器全局的Hadoop依赖。
  • 可以在代码初始化阶段加一段校验逻辑,部署后打印类的加载来源,快速定位类路径问题:
try {
  val localFsClass = Class.forName("org.apache.hadoop.fs.LocalFileSystem")
  println(s"LocalFileSystem加载成功,来源路径:${localFsClass.getProtectionDomain.getCodeSource.getLocation}")
} catch {
  case e: ClassNotFoundException =>
    println("运行时类路径缺失hadoop-common包,请检查Jenkins打包、部署环节的依赖拷贝逻辑")
    throw e
}

内容的提问来源于stack exchange,提问作者Elwys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 21:01:58