如何将Windows全局程序集缓存(GAC)的DLL加载到.NET Spark的spark-submit中
问题解答
1. Windows环境下能否将GAC作为参数传递给spark-submit对应的dotnet命令?
不能。核心原因是你用的.NET Core 3.1根本不支持传统Windows GAC的程序集加载逻辑,GAC是.NET Framework专属的机制,.NET Core/.NET 5+的运行时不会主动从GAC目录扫描加载程序集。
即使你通过dotnet exec --additionalprobingpath参数把GAC根目录传给dotnet命令也没用:GAC内的dll是按版本、公钥token拆分多层子目录存储的,直接添加根目录作为探测路径,运行时也找不到对应版本的程序集。
你当前的报错本质是运行环境缺少ASP.NET Core 3.1共享框架的对应程序集,和GAC无关。
2. 若上述方案不可行,升级到.NET 5.0 SDK能否解决该问题?
不能。.NET 5及后续所有.NET版本都没有兼容GAC加载的设计,这个问题的根因没有变。就算你升级版本,只要运行Spark Worker的节点没有安装对应版本的ASP.NET Core共享运行时,或者发布应用时没有携带相关依赖,依然会报同类的程序集加载失败错误。
3. 若升级也无法解决,切换到Linux环境并通过软链接(ln)指向GAC目录的方案是否可行?
完全不可行。首先Linux系统本身就没有Windows GAC的运行机制,.NET的Linux运行时也完全不识别Windows GAC的目录结构和存储规则;其次GAC内的很多程序集是Windows专属、和.NET Framework绑定的,放到Linux环境下本身就无法和.NET Core/.NET 5+的运行时兼容,就算做了软链接也不可能正常加载。
推荐解决方案
你当前的报错最优修复方案是发布应用时采用自包含部署模式,执行发布命令:
dotnet publish -c Release -r win-x64 --self-contained true
该命令会把所有依赖的运行时、第三方程序集全部打包到发布目录,提交spark-submit任务时直接使用发布后的文件,不需要依赖运行环境安装的SDK或GAC内的文件,就能解决程序集加载失败的问题。
如果不想采用自包含部署(减小发布包体积),只需要给所有运行Spark Worker的Windows节点安装对应版本的ASP.NET Core 3.1共享运行时即可。
内容的提问来源于stack exchange,提问作者Subhasish G

