Hadoop源码分析,namenode是如何启动http服务器对外提供服务的?

分析hadoop源码首先是从启动脚本中寻找调用类

启动脚本路径:
.../hadoop/sbin/start-all.sh

vi star-all.sh 查看脚本内容
# start hdfs daemons if hdfs is present

if [ -f "${HADOOP_HDFS_HOME}"/sbin/start-dfs.sh ]; then

  "${HADOOP_HDFS_HOME}"/sbin/start-dfs.sh --config $HADOOP_CONF_DIR

fi

# start yarn daemons if yarn is present

if [ -f "${HADOOP_YARN_HOME}"/sbin/start-yarn.sh ]; then

  "${HADOOP_YARN_HOME}"/sbin/start-yarn.sh --config $HADOOP_CONF_DIR

fi


从上面脚本内容可以得出,启动hdfs是从sbin目录下的start-dfs.sh脚本启动的,于是查看start-dfs.sh脚本

#---------------------------------------------------------

# namenodes

NAMENODES=$($HADOOP_PREFIX/bin/hdfs getconf -namenodes)

echo "Starting namenodes on [$NAMENODES]"

"$HADOOP_PREFIX/sbin/hadoop-daemons.sh" \

  --config "$HADOOP_CONF_DIR" \

  --hostnames "$NAMENODES" \

  --script "$bin/hdfs" start namenode $nameStartOpt

#---------------------------------------------------------

于是发现启动namenode是调用了
/sbin/hadoop-daemons.sh +参数,于是转向hadoop-daemons.sh

#################文件内容
bin=`dirname "${BASH_SOURCE-$0}"` 

bin=`cd "$bin"; pwd`

DEFAULT_LIBEXEC_DIR="$bin"/../libexec

HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR}

. $HADOOP_LIBEXEC_DIR/hadoop-config.sh

exec "$bin/slaves.sh" --config $HADOOP_CONF_DIR cd "$HADOOP_PREFIX" \; "$bin/hadoop-daemon.sh" --config $HADOOP_CONF_DIR "$@" 
##################

通过查看shell脚本文件发现 原来是调用了sbin/hadoop-daemon.sh  -config  hadoop_conf_dir (配置文件的路径)start

于是寻找sbin/hadoop-daemon.sh 
hadoop_rotate_log $log

    echo starting $command, logging to $log

    cd "$HADOOP_PREFIX"

    case $command in

      namenode|secondarynamenode|datanode|journalnode|dfs|dfsadmin|fsck|balancer|zkfc)

        if [ -z "$HADOOP_HDFS_HOME" ]; then

          hdfsScript="$HADOOP_PREFIX"/bin/hdfs

        else

          hdfsScript="$HADOOP_HDFS_HOME"/bin/hdfs

        fi

        nohup nice -n $HADOOP_NICENESS $hdfsScript --config $HADOOP_CONF_DIR $command "$@" > "$log" 2>&1 < /dev/null &

      ;;

      (*)

        nohup nice -n $HADOOP_NICENESS $hadoopScript --config $HADOOP_CONF_DIR $command "$@" > "$log" 2>&1 < /dev/null &

      ;;

    esac


通过查看上面脚本可以发现最终转向了bin/hdfs这个脚本,所以去查看hdfs这个脚本
if [ "$COMMAND" = "namenode" ] ; then

  CLASS='org.apache.hadoop.hdfs.server.namenode.NameNode'

  # Set SENTRY_HOME if possible and add Sentry plugin jars to classpath

  if [[ -z "$SENTRY_HOME" ]]

  then

    # HADOOP_HDFS_HOME should have been set by hadoop-config.sh

    if [[ -d ${HADOOP_HDFS_HOME}/../sentry ]]

    then

      export SENTRY_HOME=`readlink -m ${HADOOP_HDFS_HOME}/../sentry`

    fi

  fi

  if [[ -n "$SENTRY_HOME" ]]

  then

    for f in ${SENTRY_HOME}/lib/plugins/*.jar; do

    CLASSPATH=${CLASSPATH}:${f}

    done


从上面可以看出原来是启动了org.apache.hadoop.hdfs.server.namenode.NameNode这个类

于是打开IDEA,搜索包路径,进入这个包的main函数路口

前面的if主要是做一些参数的校验,
启动namenode是在
NameNode namenode =createNameNode(argv,null);这一句里

最后返回一个new Namenode(conf)
之后,进入这个类

public NameNode(Configuration conf)throws IOException {

this(conf, NamenodeRole.NAMENODE);

}

/**

* 1、对namenode做参数的注册(fs.defaultFS、rpc地址等)

* 2、初始化

* 3、根据初始化处理的结果,namenode进入对应的状态(active、backup、standby)

* */

protected NameNode(Configuration conf, NamenodeRole role)

throws IOException {

this.conf = conf;

this.role = role;//保存NameNode的角色信息

//设置clients访问nomenode或nameservice的访问地址  配置项fs.defaultFS:hadoop01:9000

  setClientNamenodeAddress(conf);

String nsId = getNameServiceId(conf);

String namenodeId = HAUtil.getNameNodeId(conf, nsId);

//ha相关

  this.haEnabled = HAUtil.isHAEnabled(conf, nsId);

//根据用户设置的启动参数,确定启动以后的初始状态,如果是正常启动,则全部直接进入Standby状态

  state = createHAState(getStartupOption(conf));

this.allowStaleStandbyReads = HAUtil.shouldAllowStandbyReads(conf);

//TODO 在创建HA的时候,也启动了standByNameNode的服务

  this.haContext = createHAContext();

try {

//给联邦模式下准备的,主要是设置联邦模式下namenode的地址和RPC地址

    initializeGenericKeys(conf, nsId, namenodeId);

//TODO

    initialize(conf);

// HA相关

    try {

haContext.writeLock();

state.prepareToEnterState(haContext);

state.enterState(haContext);

}finally {

haContext.writeUnlock();

}

}catch (IOException e) {

this.stop();

throw e;

}catch (HadoopIllegalArgumentException e) {

this.stop();

throw e;

}

this.started.set(true);

}




进入到initialize方法


namenode是如何启动http服务器对外提供服务的

在启动namenode的时候在main函数里进行参数校验,校验完毕之后,根据模式匹配走到defeut,然后进到namenode构造函数,在namenode构造函数当中,会构造一个initialize(conf)这样一个初始化方法,在这个方法中,会对namenode的角色进行判断,如果当前传递过来的角色是namenode的话,此时开始启动http服务,在启动http服务过程中构建了一个NamenodeHttpServer这个类,然后调用这个类的start方法进行启动,在启动过程中主要干的事情是:在当前的http服务里进行绑定服务,也就是setUpServlets这个方法,在这个方法里不断的绑定需要的功能,然后这个start方法就把这个http服务启动完毕了。其实hadoop是通过建造者模式自己构建了一个HttpServer2。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容