在用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的階段總結,我在這裏拋磚引玉,有錯誤的地方但願你們幫忙指出哈。