整体过程
- 根据URI获取scheme信息;
- 通过scheme判断是否使用缓存;
- 如果不用缓存,则直接创建FileSystem;否则从缓存中获取;
FileSystem创建过程
- 首次使用时,通过ServiceLoader方法将FileSystem所有实现类加载到内存,并缓存所有的class对象;
- 每次通过scheme获取文件系统对应的class对象,实例化和初始化;
private static FileSystem createFileSystem(URI uri, Configuration conf
) throws IOException {
Class<?> clazz = getFileSystemClass(uri.getScheme(), conf);
FileSystem fs = (FileSystem)ReflectionUtils.newInstance(clazz, conf);
fs.initialize(uri, conf);
return fs;
}
从缓存获取FileSystem过程
- 根据url和conf创建key;
- 如果缓存中存在key,则直接返回FileSystem;否则,创建FileSystem,加入缓存并返回;
FileSystem get(URI uri, Configuration conf) throws IOException{
Key key = new Key(uri, conf);
return getInternal(uri, conf, key);
}
ServiceLoader加载的 FileSystem实现类
get()注意事项
使用get()方法获取FileSystem实例时,每个请求都会生成一个key,如果参数中没有传入用户名和密码,则每次使用同一个UserGroupInformation实例,key的hashcode相同,返回同一个FileSystem实例;反之,如果传入用户相关的参数,导致每个请求都会创建新的UserGroupInformation实例,从而key的hashcode不同,进而创建新的FileSystem实例,缓存并返回;(蛋疼的逻辑)
实验说明
传入user信息时,相同配置的两次请求,产生不同的FileSystem实例,如下图:
没有传入user信息时,相同配置的两次请求,返回相同的FileSystem实例,如下图:
参考: