[测试] 试用Hadoop 2.2中的HDFS NFS – ZisZ – 博客园

Hadoop 2.2中正式启用了hdfs nfs功能,使得hdfs的通用性迈进了一大步。在公司让小朋友搭建了一下,然后我自己进行了一点简单的试验,有一点收获,记录在此。

理论

 

 

 

使用hdfs nfs功能的话,数据访问路径如上图:用户或程序通过Linux自带的nfs client访问hdfs nfs服务,然后再由nfs网关作为hdfs的客户端访问hdfs。

这张图中,中间的节点就是nfs代理服务器(hdfs nfs proxy)或nfs网关(hdfs nfs gateway)。蓝色代表该模块是一个进程或服务,绿色代表该模块是一个库。图中还画了两条虚线,下、上线分别表示操作系统级别和分布式操作系统(hadpp)级别的内核态与用户态分界。

部署

在nfs网关上部署hdfs nfs服务所需要的程序包,按hadoop 2.2的部署方式,应该存在这两个文件:

share/hadoop/common/hadoop-nfs-2.2.0.jar

share/hadoop/hdfs/hadoop-hdfs-nfs-2.2.0.jar

配置文件不需要改,使用默认即可;默认的几个配置分别是nfs的服务端口(标准的2049)、mount的监听端口(4242),还有一个dump目录(/tmp/.hdfs-nfs)与写逻辑有关,暂不明原理。

部署完成后,启用服务,需要依次启动portmap和nfs两个服务;

$ hadoop-daemon.<span style="color: #0000ff;">sh</span><span style="color: #000000;"> start portmap</p><p>$ hadoop</span>-daemon.<span style="color: #0000ff;">sh</span> start nfs3

注意,portmap需要用root用户启动(因为portmap标准端口111,小于1024,是超级资源),而nfs服务应该用hdfs的超级用户启动。如果出现冲突,应该将操作系统本身的nfs服务停掉。

启动完成后,检查确认是否可用,其中nfs_server_ip是nfs网关的地址:

复制代码

$ rpcinfo -<span style="color: #000000;">p $nfs_server_ip</p><p>program vers proto   port</p><p></span><span style="color: #800080;">100005</span>    <span style="color: #800080;">1</span>   tcp   <span style="color: #800080;">4242</span><span style="color: #000000;">  mountd</p><p></span><span style="color: #800080;">100000</span>    <span style="color: #800080;">2</span>   udp    <span style="color: #800080;">111</span><span style="color: #000000;">  portmapper</p><p></span><span style="color: #800080;">100005</span>    <span style="color: #800080;">3</span>   tcp   <span style="color: #800080;">4242</span><span style="color: #000000;">  mountd</p><p></span><span style="color: #800080;">100005</span>    <span style="color: #800080;">2</span>   udp   <span style="color: #800080;">4242</span><span style="color: #000000;">  mountd</p><p></span><span style="color: #800080;">100003</span>    <span style="color: #800080;">3</span>   tcp   <span style="color: #800080;">2049</span><span style="color: #000000;">  nfs</p><p></span><span style="color: #800080;">100000</span>    <span style="color: #800080;">2</span>   tcp    <span style="color: #800080;">111</span><span style="color: #000000;">  portmapper</p><p></span><span style="color: #800080;">100005</span>    <span style="color: #800080;">3</span>   udp   <span style="color: #800080;">4242</span><span style="color: #000000;">  mountd</p><p></span><span style="color: #800080;">100005</span>    <span style="color: #800080;">1</span>   udp   <span style="color: #800080;">4242</span><span style="color: #000000;">  mountd</p><p></span><span style="color: #800080;">100005</span>    <span style="color: #800080;">2</span>   tcp   <span style="color: #800080;">4242</span>  mountd

复制代码

 

$ showmount -<span style="color: #000000;">e $nfs_server_ip</p><p>Export list </span><span style="color: #0000ff;">for</span> SY-<span style="color: #800080;">0245</span><span style="color: #000000;">:</p><p></span>/ *

 

挂载NFS服务

创建挂载的目录

$ <span style="color: #0000ff;">mkdir</span> /mnt/hdfs

安装mount.nfs

$ <span style="color: #0000ff;">sudo</span> apt-get <span style="color: #0000ff;">install</span> nfs-common

开始挂载

$ mount.nfs $nfs_server_ip:/ /mnt/hdfs

 

试用及分析

尝试访问/mnt/hdfs,试用了简单的ls、cp、rm等操作,也进行了md5sum,都可以正常使用,而且响应速度明显快于通过FsShell进行操作,这应该是得益于nfs的wcc缓存及hdfs nfs的实现中对连接的缓存;

但hdfs nfs是否是一个完全兼容标准文件系统接口的实现呢,为此我测试了一下最难处理的随机写和复写,代码如下,简单的说,就是做三次写,第一次写在文件头(字符1),第二次写在文件尾(字符2),第三次写在文件中间(字符3):

复制代码

#include &lt;stdio.h&gt;<span style="color: #000000;"></p><p>#include </span>&lt;stdlib.h&gt;<span style="color: #000000;"></p><p>#include </span>&lt;stdbool.h&gt;</p><p><span style="color: #0000ff;">void</span> usage(<span style="color: #0000ff;">char</span>*<span style="color: #000000;"> argv[]) {</p><p>  fprintf(stdout, </span><span style="color: #800000;">"</span><span style="color: #800000;">%s &lt;file_length&gt;\n</span><span style="color: #800000;">"</span>, argv[<span style="color: #800080;">0</span><span style="color: #000000;">]);</p><p>  fprintf(stdout, </span><span style="color: #800000;">"</span><span style="color: #800000;">NOTE:\n</span><span style="color: #800000;">"</span><span style="color: #000000;">);</p><p>  fprintf(stdout, </span><span style="color: #800000;">"</span><span style="color: #800000;">    file_length &gt;= 3\n</span><span style="color: #800000;">"</span><span style="color: #000000;">);</p><p>}</p><p></span><span style="color: #0000ff;">bool</span> open_and_check(FILE** fpp, <span style="color: #0000ff;">int</span><span style="color: #000000;"> op_seq) {</p><p>  (</span>*fpp) = fopen(<span style="color: #800000;">"</span><span style="color: #800000;">testfile</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">r+</span><span style="color: #800000;">"</span><span style="color: #000000;">);</p><p>  </span><span style="color: #0000ff;">if</span> ((*fpp) ==<span style="color: #000000;"> NULL) {</p><p>    fprintf(stderr, </span><span style="color: #800000;">"</span><span style="color: #800000;">%d.Can not open test file.\n</span><span style="color: #800000;">"</span><span style="color: #000000;">, op_seq);</p><p>    </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">;</p><p>  }</p><p>  </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #000000;">;</p><p>}</p><p></span><span style="color: #0000ff;">int</span> main(<span style="color: #0000ff;">int</span> args, <span style="color: #0000ff;">char</span>*<span style="color: #000000;"> argv[]) {</p><p>  </span><span style="color: #0000ff;">if</span> (args != <span style="color: #800080;">2</span><span style="color: #000000;">) {</p><p>    usage(argv);</p><p>    </span><span style="color: #0000ff;">return</span> -<span style="color: #800080;">1</span><span style="color: #000000;">;</p><p>  }</p><p>  </span><span style="color: #0000ff;">int</span> length = atoi(argv[<span style="color: #800080;">1</span><span style="color: #000000;">]);</p><p>  </span><span style="color: #0000ff;">if</span> (length &lt; <span style="color: #800080;">3</span><span style="color: #000000;">) {</p><p>    fprintf(stdout, </span><span style="color: #800000;">"</span><span style="color: #800000;">file_length must be at least 3\n</span><span style="color: #800000;">"</span><span style="color: #000000;">);</p><p>    </span><span style="color: #0000ff;">return</span> -<span style="color: #800080;">1</span><span style="color: #000000;">;</p><p>  }</p><p>  fclose(fopen(</span><span style="color: #800000;">"</span><span style="color: #800000;">testfile</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">w+</span><span style="color: #800000;">"</span><span style="color: #000000;">));</p><p>  FILE</span>*<span style="color: #000000;"> fp;</p><p>  </span><span style="color: #0000ff;">int</span> op_seq = <span style="color: #800080;">1</span><span style="color: #000000;">;</p><p>  </span><span style="color: #0000ff;">if</span> (!open_and_check(&amp;<span style="color: #000000;">fp, op_seq))</p><p>    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> op_seq;</p><p>  putc(</span><span style="color: #800000;">'</span><span style="color: #800000;">0</span><span style="color: #800000;">'</span>+op_seq, fp); <span style="color: #008000;">//</span><span style="color: #008000;"> '1'</span></p><p><span style="color: #000000;">  fclose(fp);</p><p>  op_seq</span>++<span style="color: #000000;">;</p><p>  </span><span style="color: #0000ff;">if</span> (!open_and_check(&amp;<span style="color: #000000;">fp, op_seq))</p><p>    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> op_seq;</p><p>  fseek(fp, length, SEEK_SET);</p><p>  putc(</span><span style="color: #800000;">'</span><span style="color: #800000;">0</span><span style="color: #800000;">'</span>+op_seq, fp); <span style="color: #008000;">//</span><span style="color: #008000;"> '2'</span></p><p><span style="color: #000000;">  fclose(fp);</p><p>  op_seq</span>++<span style="color: #000000;">;</p><p>  </span><span style="color: #0000ff;">if</span> (!open_and_check(&amp;<span style="color: #000000;">fp, op_seq))</p><p>    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> op_seq;</p><p>  fseek(fp, length</span>/<span style="color: #800080;">2</span><span style="color: #000000;">, SEEK_SET);</p><p>  putc(</span><span style="color: #800000;">'</span><span style="color: #800000;">0</span><span style="color: #800000;">'</span>+op_seq, fp); <span style="color: #008000;">//</span><span style="color: #008000;"> '3'</span></p><p><span style="color: #000000;">  fclose(fp);</p><p>  </span><span style="color: #008000;">//</span><span style="color: #008000;">op_seq++;</span></p><p>  <span style="color: #0000ff;">return</span> <span style="color: #800080;">0</span><span style="color: #000000;">;</p><p>}</span>

复制代码

注:参数n是第二次写之前做的偏移量,因而实际文件长度会是n+1

 

1. 首先用一个小文件做测试,如下:

root@xxx:/mnt/hdfs/tmp# ./a.out <span style="color: #800080;">3</span><span style="color: #000000;"></p><p>root@xxx:</span>/mnt/hdfs/tmp# <span style="color: #0000ff;">ls</span> -<span style="color: #000000;">l testfile </p><p></span>-rw-r--r-- <span style="color: #800080;">1</span> root root <span style="color: #800080;">4</span> Nov <span style="color: #800080;">27</span> <span style="color: #800080;">18</span>:<span style="color: #800080;">04</span><span style="color: #000000;"> testfile</p><p>root@xxx:</span>/mnt/hdfs/tmp# <span style="color: #0000ff;">cat</span><span style="color: #000000;"> testfile </p><p></span><span style="color: #800080;">132</span>

结果都符合预期;

 

2. 如果再重复执行一次呢?

root@xxx:/mnt/hdfs/tmp# ./a.out <span style="color: #800080;">3</span><span style="color: #000000;"></p><p>Segmentation fault (core dumped)</span>

从hdfs nfs网关的日志中可以找到出错的原因:

2013-11-27 18:11:53,695 ERROR org.apache.hadoop.hdfs.nfs.nfs3.RpcProgramNfs3: Setting file size is not supported when setattr, fileId: 20779

不支持重置文件大小,也就是不支持truncate,至少还“正确地”返回了失败;

 

3. 改变文件大小测试一下

复制代码

root@SY-<span style="color: #800080;">0266</span>:/mnt/hdfs/tmp# ./a.out <span style="color: #ff0000;">4096</span> &amp;&amp; <span style="color: #0000ff;">ls</span> -lh --full-<span style="color: #0000ff;">time</span> testfile &amp;&amp; <span style="color: #0000ff;">sleep</span> <span style="color: #800080;">5</span> &amp;&amp; <span style="color: #0000ff;">ls</span> -lh --full-<span style="color: #0000ff;">time</span><span style="color: #000000;"> testfile</p><p></span>-rw-r--r-- <span style="color: #800080;">1</span> root root <span style="color: #ff0000;">2.1K</span> <span style="color: #800080;">2013</span>-<span style="color: #800080;">11</span>-<span style="color: #800080;">27</span> <span style="color: #800080;">22</span>:<span style="color: #800080;">22</span>:<span style="color: #800080;">40.572000000</span> +<span style="color: #800080;">0800</span><span style="color: #000000;"> testfile</p><p></span>-rw-r--r-- <span style="color: #800080;">1</span> root root <span style="color: #ff0000;">1</span> <span style="color: #800080;">2013</span>-<span style="color: #800080;">11</span>-<span style="color: #800080;">27</span> <span style="color: #800080;">22</span>:<span style="color: #800080;">22</span>:<span style="color: #800080;">40.572000000</span> +<span style="color: #800080;">0800</span><span style="color: #000000;"> testfile</p><p>root@SY</span>-<span style="color: #800080;">0266</span>:/mnt/hdfs/tmp# <span style="color: #0000ff;">rm</span><span style="color: #000000;"> testfile </p><p>root@SY</span>-<span style="color: #800080;">0266</span>:/mnt/hdfs/tmp# ./a.out <span style="color: #ff0000;">4095</span> &amp;&amp; <span style="color: #0000ff;">ls</span> -lh --full-<span style="color: #0000ff;">time</span> testfile &amp;&amp; <span style="color: #0000ff;">sleep</span> <span style="color: #800080;">5</span> &amp;&amp; <span style="color: #0000ff;">ls</span> -lh --full-<span style="color: #0000ff;">time</span><span style="color: #000000;"> testfile</p><p></span>-rw-r--r-- <span style="color: #800080;">1</span> root root <span style="color: #ff0000;">4.0K</span> <span style="color: #800080;">2013</span>-<span style="color: #800080;">11</span>-<span style="color: #800080;">27</span> <span style="color: #800080;">22</span>:<span style="color: #800080;">25</span>:<span style="color: #800080;">17.606000000</span> +<span style="color: #800080;">0800</span><span style="color: #000000;"> testfile</p><p></span>-rw-r--r-- <span style="color: #800080;">1</span> root root <span style="color: #ff0000;">4.0K</span> <span style="color: #800080;">2013</span>-<span style="color: #800080;">11</span>-<span style="color: #800080;">27</span> <span style="color: #800080;">22</span>:<span style="color: #800080;">25</span>:<span style="color: #800080;">17.606000000</span> +<span style="color: #800080;">0800</span> testfile

复制代码

可以发现从4K开始,向上的文件已经无法正常完成这个测试了,文件会隐性的丢失数据。这应该与hdfs nfs对随机写和复写的实现有关,我没有具体研究代码。

 

从这个简单测试可以得出结论,hdfs nfs可以进行简单的文件读写、使用常用的shell命令操作,但决不可以直接当本地文件系统、通过程序进行访问。

来源URL:http://www.cnblogs.com/ZisZ/p/3437880.html