Hadoop NameNode端口问题

      今天被前同事问起NameNode都启动了哪些端口,分别是IPC server, Http Server, jmx Server,但是netstat -anlp发现不止有三个,是五个。经过我同事分析,多出的两个是

启动java 的profile 参数(jvisualvm的参数)

-Dcom.sun.management.jmxremote=true
-Djava.rmi.server.hostname=ip
-Dcom.sun.management.jmxremote.port=9986
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

注意:这里这一组参数会启动3个端口,分别是因为 com.sun.management.jmxremote=true 启动一个随机
com.sun.management.jmxremote.port=9986 启动一个9986端口以及再启动一个额外的随机端口

正是因为hadoop-env.sh脚本中带有-Dcom.sun.management.jmxremote 属性,才导致hadoop本身又多起了一个端口

Hadoop Pipeline详解

一、说明
Hadoop 2.x相比较于1.x有了较大的改变,像MapReduce层面架构以及代码基本上是完全重写的,在HDFS层面加入了HA,Federation等特性,代码更加层次化和易读,同时加入的PB初期可能给阅读带来障碍,熟悉之后就没有太大问题了。
Pipeline一只是Hadoop重要的一个过程,不管是MR任务,Hive任务等等,最后都需要Pipeline将数据写入到HDFS中。所以熟悉Hadoop Pipeline过程还是很有意义的。

二、流程说明
Hadoop pipeline的建立可以由以下的流程图来说明,Pipeline建立牵扯的有NameNode,DataNode,DFSClient等结构。
pipe1
以下为简要说明
1、首先DFSClient向NameNode发送RPC Create请求,NameNode在INode中生成新的INodeFile并加入到新的LeaseManager中作为稍后写入的租约管理。
2、请求成功返回后,DFSClient生成一个OutputStream,既DFSOutputStream
3、行程pipeline之前向NameNode发送AddBlock请求,NameNode生成新的Block,选择要写入的DataNode节点,并将Block注册到INodeFile中,以及BlockManager中,准备写入
4、建立pipeline,根据NameNode返回的信息,找到一个primary Datanode作为第一个节点,准备写入
5、DataNode Socket接收后,首先将数据写入buffer中,然后写入到下一个节点,写入成功后将buffer中数据写入本地磁盘,并等待ACK信息
6、与5一样,写入下一个节点然后写入本地,最后等待ACK信息
7、如果ACK都成功返回后,发回给DFSClient,本次写入成功。

三、详细说明
Continue reading…

Hadoop FastCopy

一、背景

      Hadoop目前使用Distcp作为集群间的数据传输工具,但是Hadoop2.0 可以采用federation,每个ns公用存储节点,这样还采用Distcp作为集群间数据传输将会非常浪费,直接的想法就是能够通过硬链接将federation中共用存储的block也进行共享,就会大大的节省带宽,IO,网络以及时间。

 

 

 

二、流程说明

 



Fastcopy1

      整体流程如图,以下为简要说明:

1、Client首先向Source NS1获取需要拷贝的文件的block location

2、对每一个block,根据Source得Location向Dest NS2申请block,并尽量申请到同一个DataNode节点

3、向DataNode发送File copy的RPC请求

4、DataNode获得请求后查看源DataNode和目的DataNode是否是同一台机器上的同一个实例的DataNode,如果是通过hard link完成copy

5、如果不是,退化为常规的机器间拷贝


JournalNode性能测试

一、背景

 

    Hadoop 2 开始采用JournalNode作为共享存储,JournalNode由NameNode部分的QuorumJournalManager,IPCLoggerChannel及JournalNode Server端的JournalNodeRPCServer组成。

 

    IPCLoggerChannel由一个JournalNode对应一个线程去完成日志的发送,保证日志的有序性,同时根据Paxos算法,绝大多数JournalNode完成回应就算完成日志发送。

 

    原先Hadoop 1采用的是本地记录Editlog并在远程NFS上记录一份,使用JournalNode后,我们需要获得相应的数据来比较JournalNode性能及对NameNode的影响。

 

 

 

二、测试方法

 

    分别采用1,3,5台机器组成journalNode,测试每分钟写入的日志数,并且与大集群相比,得到比较结果。

 

    以下数据是从大集群获得的每分钟edit transaction数,一般的峰值不到10万。


Jn2

    以下是单节点JournalNode接收数量:

Jn1

    五个节点JournalNode接收数量:

Jn3

    综合上述数据,我们可以确定,即使使用journalnode,也能保证我的NameNode的并发性能。

jvisualvm使用说明

   调试程序,需要找到程序热点,尤其是多线程程序,线程的等待时间,各个耦合系统之间的调用时间都需要仔细的进行监控从而获得系统性能的一个大概了解。

 jvisualvm使用起来相当方便,可以进行远程调试,满足最基本的需求。

   远程配置:需要在服务器端配置调试选项

   java  -Djava.rmi.server.hostname=10.73.20.72

-Dcom.sun.management.jmxremote=true

-Dcom.sun.management.jmxremote.port=9999

-Dcom.sun.management.jmxremote.ssl=false

-Dcom.sun.management.jmxremote.authenticate=false   com.sina.mis.calligraphus.core.Calligraphus 

注意:一般来说需要配置java.rmi.server.hostname属性,配置位服务器的ip地址,剩下的是端口,和不采用任何认证方式,便于调试。

   在本地打开jvisualvm,打开远程调试,键入地址,选择添加jmx connection,地址和端口,端口即上面配置的端口。就可以使用了,主要是hostname的配置。

 

Mac 下修改Eclipse内存

    Mac下如果Eclipse使用默认的参数会非常非常痛苦的,甚至退化到Windows时候的感觉。所以下载Eclipse以后第一步就是设置Eclipse JVM参数,设置的位置为$ECLIPSE_HOME/Eclipse.app/Contents/MacOS/eclipse.ini。加入以下参数

    -vmargs

    -Xms512m

    -Xmx2048m

 

    其中$ECLIPSE_HOME是你安装Eclipse的home目录。

Maven加入新的source问题

    最近将之前做的hadoop-raid移植到2.4.0上面,因为之前的RPC都是通过POJO,而现在2.x的RPC都是通过PB(参见我之前写过的Blog),所以需要将新加入的Protocol进行PB的改写。

    其中写好proto文件后,需要用hadoop写好的hadoop-maven-plugin插件将proto文件生成java文件。

 <plugin>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-maven-plugins</artifactId>
        <executions>
          <execution>
            <id>compile-protoc-raid</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>protoc</goal>
            </goals>
            <configuration>
              <protocVersion>${protobuf.version}</protocVersion>
              <protocCommand>${protoc.path}</protocCommand>
              <imports>
                <param>${basedir}/../../hadoop-common-project/hadoop-common/src/main/proto</param>
                <param>${basedir}/src/main/proto</param>
              </imports>
              <source>
                <directory>${basedir}/src/main/proto</directory>
                <includes>
                  <include>RaidProtocol.proto</include>
                </includes>
              </source>
              <output>${project.build.directory}/generated-sources/java</output>
            </configuration>
          </execution>
        </executions>
      </plugin>

    同时需要将生成的java文件加入ClassPath中,采用的是org.codehaus.mojo.build-helper-maven-plugin插件。

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <executions>
          <execution>
            <id>add-raid-generated-sources-directory</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>add-source</goal>
            </goals>
            <configuration>
              <sources>
                <source>${project.build.directory}/generated-sources/java</source>
              </sources>
            </configuration>
          </execution>
        </executions>
      </plugin>

    但是使用后能够在terminal中顺利编译,而eclipse却显示没有加入这个classpath。

    最后想到还是用maven命令生成一遍,mvn clean generate-sources eclipse:eclipse

就解决问题了。