hadoop.fs.FileSystem.get导致OOM的原因和解决方案

问题描述

在调用HDFS获取文件系统的get接口时,指定用户可能会导致OOM问题,示例代码如下:

FileSystem fileSystem = FileSystem.get(uri, conf, "hadoopuser");

问题溯源

该方法源码:
在这里插入图片描述
在有缓存的情况下将从Cache中取,一路取下去最后会从map中根据key取内容
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
但如果指定了user,此处根据key只能取到空值,
原因:
如下图所示,Cache的map的Key中包括了UserGroupInformation ugi,上述拿值时候会以此类型作为Key在这里插入图片描述回到指定用户名时最初调用的get方法,源码如下:

  public static FileSystem get(final URI uri, final Configuration conf,
        final String user) throws IOException, InterruptedException {
    String ticketCachePath =
      conf.get(CommonConfigurationKeys.KERBEROS_TICKET_CACHE_PATH);
    //进入getBestUGI查看一下源码
    UserGroupInformation ugi =
        UserGroupInformation.getBestUGI(ticketCachePath, user);
    return ugi.doAs(new PrivilegedExceptionAction<FileSystem>() {
      @Override
      public FileSystem run() throws IOException {
        return get(uri, conf);
      }
    });
  }

getBestUGI查看源码:

  public static UserGroupInformation getBestUGI(
      String ticketCachePath, String user) throws IOException {
    if (ticketCachePath != null) {
      return getUGIFromTicketCache(ticketCachePath, user);
    } else if (user == null) {
      return getCurrentUser();
    } else {
    //注意这一句,查看一下源码
      return createRemoteUser(user);
    }    
  }

createRemoteUser源码

@InterfaceAudience.Public
  @InterfaceStability.Evolving
  public static UserGroupInformation createRemoteUser(String user, AuthMethod authMethod) {
    if (user == null || user.isEmpty()) {
      throw new IllegalArgumentException("Null user");
    }
    //此处subject一直是新的
    Subject subject = new Subject();
    subject.getPrincipals().add(new User(user));
    UserGroupInformation result = new UserGroupInformation(subject);
    result.setAuthenticationMethod(authMethod);
    return result;
  }

可以看出,在指定了用户名的情况下一直会新建subject,那么如何判断两个key是否相等呢?查看一下Cache重写的hashCode方法:

 public int hashCode() {
        return (scheme + authority).hashCode() + ugi.hashCode() + (int)unique;
      }

可以看出在判断两个Key值是否一致时,会判断ugi的hashCode是否一致,其中ugi.hashCode代码如下,又能够看出判断ugi的hashCode是否一致会去判断subject的hashCode是否一致,而上面说过的,调用createRemoteUser每次都会新建一个subject,这也就导致了这两个Key值永远是不同的,用这个Key值取也一定是取不到值的:

public int hashCode() {
    return System.identityHashCode(subject);
  }

在取不到值的情况下,getInternal中的下列语句就会一直被执行到

 map.put(key, fs);

最终导致OOM

解决方法

自己定义一个map缓存,调用FileSystem.newInstance,不使用FileSystem的cache

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值