在用Hadoop框架处理大数据时使用最多就是HDFS--分布式文件系统,但Hadoop的文件系统不只只有分布式文件系统,例如:hfs,HSFTP,HAR等在Hadoop中都是有集成的,用来处理存储在不一样体系中的数据。事实上应该这么说,Hadoop实际上是一个综合性的文件系统。html
下面来看看文件系统的结构体系java
固然上面的UML图解事实上有些冗余,可是为了能清楚的表达fs这个体系中的成员,我尽可能把全部的成员罗列了进来。在Hadoop的文件系统体系中FileSystem是其余成员的父类,它是一个抽象类,旨在经过它来定义一个访问文件系统的标准,在Hadoop框架中的其余组件在使用到文件系统时只认识FileSystem类提供的标准,因此若是本身在定义一个文件系统是定要按照这个标准来(固然,说说而已,我也没尝试过),面对抽象编程在我看来就是按照某些标准来编程。至于在FileSystem的子类中,到底仅仅是实现了抽象的方法,仍是同时也重写了父类的方法,我以为不重要,最重要的是明白这种设计思想。web
在使用文件系统是通常的经过FileSystem.get(Configuration conf)或者是FileSystem.get(URI uri,Configuration conf)来获取文件系统的实例,这两种方法时高度一致的,咱们来看看源码apache
public static FileSystem get(URI uri, Configuration conf) throws IOException { String scheme = uri.getScheme(); String authority = uri.getAuthority(); if (scheme == null) { // no scheme: use default FS return get(conf); } if (authority == null) { // no authority URI defaultUri = getDefaultUri(conf); if (scheme.equals(defaultUri.getScheme()) // if scheme matches default && defaultUri.getAuthority() != null) { // & default has authority return get(defaultUri, conf); // return default } } String disableCacheName = String.format("fs.%s.impl.disable.cache", scheme); if (conf.getBoolean(disableCacheName, false)) { return createFileSystem(uri, conf); } return CACHE.get(uri, conf); } /** Returns the configured filesystem implementation.*/ public static FileSystem get(Configuration conf) throws IOException { return get(getDefaultUri(conf), conf); } public static URI getDefaultUri(Configuration conf) { return URI.create(fixName(conf.get(FS_DEFAULT_NAME_KEY, "file:///"))); }
在调用FileSystem.get(Configuration conf)的时候,事实上仍是调用了FileSystem.get(URI uri,Configuration conf),使用FileSystem.get(Configuration conf)来获取文件系统的实例时会去读取配置文件core-site.xml中键fs.default.name对应的value,若是不存在该项配置,默认使用的file:///也就是本地文件系统。使用FileSystem.get(conf)方法时,会去读取配置文件,这样在后期更换文件系统时就很方便了。固然使用FileSystem.get(uri,conf)时也能够很好的实现后期文件系统的修改,直接在程序运行时加入参数就好了。如今剩下的问题就落在FileSystem.get(uri,conf)的头上了,大权握在它的手上了。来看看经过这个方法是怎么获得具体的文件系统实例的,在验证uri的结构完整后,经过createFileSystem(uri, conf)来返回FileSystem的实例,在CACHE.get(uri, conf)方法的内部一样也会调用createFileSystem(uri, conf),那么问题就落在了这个方法上了,下面来看看createFileSystem(uri, conf)的源码,就明白了是怎么回事了
编程
private static FileSystem createFileSystem(URI uri, Configuration conf ) throws IOException { Class<?> clazz = conf.getClass("fs." + uri.getScheme() + ".impl", null); LOG.debug("Creating filesystem for " + uri); if (clazz == null) { throw new IOException("No FileSystem for scheme: " + uri.getScheme()); } FileSystem fs = (FileSystem)ReflectionUtils.newInstance(clazz, conf); fs.initialize(uri, conf); return fs; }
这下就明了了,Class<?> clazz = conf.getClass("fs." + uri.getScheme() + ".impl", null);经过读取core-default.xml中fs.[scheme].impl的value值来获得FileSystem实现类的字节码文件,有了Class文件其余的事情就好说了,此时至关因而把整个类的全部细节都暴露给programmer了,经过反射技术操做Class从而就获得了文件系统的实例。下面是core-default.xml中关于这部分的配置片断设计模式
<property> <name>fs.file.impl</name> <value>org.apache.hadoop.fs.LocalFileSystem</value> <description>The FileSystem for file: uris.</description> </property> <property> <name>fs.hdfs.impl</name> <value>org.apache.hadoop.hdfs.DistributedFileSystem</value> <description>The FileSystem for hdfs: uris.</description> </property> <property> <name>fs.s3.impl</name> <value>org.apache.hadoop.fs.s3.S3FileSystem</value> <description>The FileSystem for s3: uris.</description> </property> <property> <name>fs.s3n.impl</name> <value>org.apache.hadoop.fs.s3native.NativeS3FileSystem</value> <description>The FileSystem for s3n: (Native S3) uris.</description> </property> <property> <name>fs.kfs.impl</name> <value>org.apache.hadoop.fs.kfs.KosmosFileSystem</value> <description>The FileSystem for kfs: uris.</description> </property> <property> <name>fs.hftp.impl</name> <value>org.apache.hadoop.hdfs.HftpFileSystem</value> </property> <property> <name>fs.hsftp.impl</name> <value>org.apache.hadoop.hdfs.HsftpFileSystem</value> </property> <property> <name>fs.webhdfs.impl</name> <value>org.apache.hadoop.hdfs.web.WebHdfsFileSystem</value> </property> <property> <name>fs.ftp.impl</name> <value>org.apache.hadoop.fs.ftp.FTPFileSystem</value> <description>The FileSystem for ftp: uris.</description> </property> <property> <name>fs.ramfs.impl</name> <value>org.apache.hadoop.fs.InMemoryFileSystem</value> <description>The FileSystem for ramfs: uris.</description> </property> <property> <name>fs.har.impl</name> <value>org.apache.hadoop.fs.HarFileSystem</value> <description>The filesystem for Hadoop archives. </description> </property>
在上面的文件系统体系图中有三处被标记的类,下面经过这三个类来讲说文件系统可否支持验证检验和的设置。什么是检验和?检验和是在文件写入或者是读取阶段用来验证数据大小是否存在差池的数据统计信息(姑且这么说),检验和的做用主要是保证数据的完整性。在hadoop中保证数据的完整性就是经过读写时对检验和的验证来实现。在hadoop的FS中,不是全部的底层文件系统都支持验证检验和的。经过LocalFileSystem和RawLocalFileSystem来讲明什么样的底层文件系统支持验证检验和。api
LocalFileSystem是一个支持验证检验和的文件系统框架
public LocalFileSystem() { this(new RawLocalFileSystem()); } public FileSystem getRaw() { return rfs; } public LocalFileSystem(FileSystem rawLocalFileSystem) { super(rawLocalFileSystem); rfs = rawLocalFileSystem; }
上面是LocalFileSystem的构造函数,从构造函数能够看出,LocalFileSystem底层使用就是RawLocalFileSystem(不支持验证检验和),在这里应该能够看出此处使用的设计模式中的装饰模式。分布式
从图中能够看出LocalFileSystem并没直接实现FileSystem,而且在hadoop权威指南中这样说的在hadoop的FS中继承了ChecksumFileSystem的FS才具备验证检验和的能力,不难想象,验证和的功能是在FilterFileSystem中完成的。看看源码就知道这种设计模式是策略模式,FilterFileSystem只对继承了FileSystem的类感兴趣。下面简单的看下ChecksumFileSystem和FilterFileSystem的构造函数。函数
ChecksumFileSystem
public ChecksumFileSystem(FileSystem fs) { super(fs); }
FilterFileSystem
protected FileSystem fs; /* * so that extending classes can define it */ public FilterFileSystem() { } public FilterFileSystem(FileSystem fs) { this.fs = fs; this.statistics = fs.statistics; }
从上面的三个类构造函数能够看出,RawLocalFileSystem的实例最终存储在FilterFileSystem的protected字段FileSystem fs中,而后调用FilterFileSystem的访问文件系统的相关方法实际上最后都避免不了调用字段fs对应的方法。so,hadoop中的FS继承了ChecksumFileSystem的就具备验证检验和的能力,例如还有InMemoryFileSystem也支持验证检验和。那么对于hadoop中其余的没有继承ChecksumFileSystem的文件系统该怎么支持验证检验和?从checkSumFileSystem和FilterFileSystem的构造函数不能看出,将任何一个继承了FileSystem的类包装下就能够实现验证检验和的功能。如想对DistributedFileSystem的实例添加验证检验和的能力,使用 new ChecksumFileSystem(dfs)就ok了,我把ChecksumFileSystem这个类称做文件系统的外套,披上了这层外套文件系统就变得更增强壮。
以上的内容是对本身学习hadoop的阶段总结,我在这里抛砖引玉,有错误的地方但愿你们帮忙指出哈。