公司使用s3的路径去关联hive的分区,现在接入spark on k8s引入了3.0以上的hadoop版本,高版本的hadoop版本开始支持s3a配置。
spark想要支持访问s3的数据,有两个条件
1、加入hadoop-aws和aws-sdk的jar包到spark/jar目录,hadoop3以上的aws-sdk jar是aws-jdk-java-bundle,注意两个jar包的版本一定要对上,不然大概率会报错,hadoop-aws的版本也尽量和spark带hadoop版本一致。例如hadoop-aws-3.3.1对应aws-java-sdk-bundle:1.11.901。不知道对应版本,可以把hadoop-aws依赖导入idea,然后maven工具那里可以看到。
2、添加配置
spark.hadoop.fs.s3a.access.key *******
spark.hadoop.fs.s3a.secret.key *******
spark.hadoop.fs.s3a.impl org.apache.hadoop.fs.s3a.S3AFileSystem
上诉配置,如果在spark中使用了s3的路径,会以下问题
上图是我试图去在spark上创建hive表指定路径为s3导致,如果是查询hive也会遇到一样的问题 No FileSystem for scheme "s3"
CREATE TABLE `tmp`.`tmp_watch_base_user` (
`uid` STRING COMMENT '用户id',
`game_key` STRING COMMENT 'game_key',
`host_id` STRING COMMENT 'host_id',
`platform` STRING COMMENT 'platform',
`day` BIGINT COMMENT 'day',
`watch_time` INT COMMENT '时间',
`first_watch_hour` STRING COMMENT 'first_watch_hour')
USING orc
LOCATION 's3://mybucket/hive/tmp.db/tmp_watch_base_user';
找遍网上所有的帖子,都没说解决s3和s3a的兼容问题,考虑到如果有问题,需要回滚的原因,不能轻易修改元数据,自己想了两个方向
1、从hive-metadata模块获取元数据的时候,将拿到的location中的s3替换成s3a。
2、修改hadoop-common包下的Path,原因是所有访问文件系统的路径都会封装到Path中,Path调用getFileSystem方法去获取文件系统,可以在uri进入Path后,手动把s3替换成s3a。
上诉两种方法改起源码来考虑的东西太多,试了一整天后没啥进展,怀着侥幸的心理,再去看一下hadoop的源码,看看有没有什么漏掉的配置,果不其然,在FileSystem的类下,看到加载文件系统的方法getFileSystemClass,通过加载java class的方式
public static Class<? extends FileSystem> getFileSystemClass(String scheme,
Configuration conf) throws IOException {
if (!FILE_SYSTEMS_LOADED) {
loadFileSystems();
}
LOGGER.debug("Looking for FS supporting {}", scheme);
Class<? extends FileSystem> clazz = null;
if (conf != null) {
String property = "fs." + scheme + ".impl";
LOGGER.debug("looking for configuration option {}", property);
clazz = (Class<? extends FileSystem>) conf.getClass(
property, null);
} else {
LOGGER.debug("No configuration: skipping check for fs.{}.impl", scheme);
}
if (clazz == null) {
LOGGER.debug("Looking in service filesystems for implementation class");
clazz = SERVICE_FILE_SYSTEMS.get(scheme);
} else {
LOGGER.debug("Filesystem {} defined in configuration option", scheme);
}
if (clazz == null) {
throw new UnsupportedFileSystemException("No FileSystem for scheme "
+ "\"" + scheme + "\"");
}
LOGGER.debug("FS for {} is {}", scheme, clazz);
return clazz;
}
使用可以配置去加载指定的文件系统,也就是上面我们配置的 spark.hadoop.fs.s3a.impl=org.apache.hadoop.fs.s3a.S3AFileSystem
String property = "fs." + scheme + ".impl";
想了想,scheme是从路径上获取,那s3路径的配置应该是spark.hadoop.fs.s3.impl,对应的文件系统应该是
org.apache.hadoop.fs.s3.S3FileSystem,但是很遗憾这个类在hadoop3后就删除了,后来又想s3a是s3的升级版,说不定s3a的文件系统可以适合s3,就使用下述配置,结果是可行的。
spark.hadoop.fs.s3.impl=org.apache.hadoop.fs.s3a.S3AFileSystem
问题不复杂,但是在做的过程中,找不到相关有用的帖子,导致心情浮躁,以为这个问题很不常见,其实如果静下心来从头看一下源码,或许这个问题2分钟就搞定了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。