当前位置:   article > 正文

Centos7搭建Hadoop HA完全分布式集群(6台机器)(内含hbase,hive,flume,kafka,spark,sqoop,phoenix,storm)_centos7 hbase安装

centos7 hbase安装

​​​​

角色担任

软件匹配说明

Hadoop HA

软件包下载

先选好Spark:3.0.1

对应的Hadoop:3.2和2.7中选一个,综合上面的图,2.7无法使用HBase,只能选3.2了

#hadoop软件:

http://mirror.bit.edu.cn/apache/hadoop/common/hadoop-3.2.1/hadoop-3.2.1-src.tar.gz

#spark软件:

http://archive.apache.org/dist/spark/spark-3.0.1/spark-3.0.1-bin-hadoop3.2.tgz

#spark源码

http://archive.apache.org/dist/spark/spark-3.0.1/spark-3.0.1.tgz

#hadoop源码

http://mirror.bit.edu.cn/apache/hadoop/common/hadoop-3.2.1/hadoop-3.2.1.tar.gz

HBase:2.3.3

http://archive.apache.org/dist/hbase/2.3.3/hbase-2.3.3-bin.tar.gz

Hive: 3.1.2

http://archive.apache.org/dist/hive/hive-3.1.2/apache-hive-3.1.2-bin.tar.gz

ZooKeeper: 3.5.5

http://archive.apache.org/dist/zookeeper/zookeeper-3.5.5/apache-zookeeper-3.5.5-bin.tar.gz

Kafka:2.6-scala2.12

http://mirror.bit.edu.cn/apache/kafka/2.6.0/kafka_2.12-2.6.0.tgz

Flume:1.9

http://mirror.bit.edu.cn/apache/flume/1.9.0/apache-flume-1.9.0-bin.tar.gz

HBase HA

Spark

Storm HA

采用6台机器

       主机名            ip            对应的角色

       Master        188.2.11.148         namenode(主)

       Slave1        188.2.11.149         namenode2,datanode1(主备,从1)

       Slave2        188.2.11.150         datanode2(从2)

       Slave3        188.2.11.151         datanode3(从3)

       Slave4        188.2.11.152         datanode4(从4)

       Slave5        188.2.11.153         datanode5(从5)

前期配置

1.修改主机名(6台机器都要操作,以Master为举例)

    hostnamectl set-hostname Master(永久修改主机名)

    reboot(重启系统)

2.修改hosts(6台机器都要操作,以Master举例)

188.2.11.148      Master

188.2.11.149      Slave1

188.2.11.150      Slave2

188.2.11.151      Slave3

188.2.11.152      Slave4

188.2.11.153      Slave5

3.准备hadoop专用用户

    adduser kfs   创建kfs用户

    passwd kfs    设置用户密码

4.尝试能否ping通(6台机器都要操作,以Master举例)

    ping -c 3 Slave1

5.ssh生成密钥(6台机器都要操作)

    ssh-keygen -t rsa (连续三次回车)

a.登录三台主机上分别执行 ssh-keygen -t rsa 生成公钥和私钥,
b.将三台主机的公钥分别追加到主机的~/.ssh/authorized_keys,在登录三台主机后都执行以下三条命令
ssh-copy-id -i ~/.ssh/id_rsa.pub 用户@节点1
ssh-copy-id -i ~/.ssh/id_rsa.pub 用户@节点2
ssh-copy-id -i ~/.ssh/id_rsa.pub 用户@节点3

经过上面操作节点1、节点12,节点13就可以无密码相互登录
检查是否配置正确,以在节点1机器操作示例
ssh 节点1
ssh 节点1
均可以实现无密码登录

也可以下操作方法

6.切换到.ssh目录下,查看公钥和私钥,并将id_rsa.pub复制到authorized_keys,然后将6台机器的authorized_key复制到本地将内容合并

    cd .ssh

    cp id_rsa.pub authorized_keys

7.来到root用户下为.ssh赋值权限   

    su root

    cd ..

    chmod 700 .ssh

    chmod 600 .ssh/authorized_keys

8.ssh 与别的节点无密钥连接(6台机器都需要进行无密钥连接,master举例)

    ssh slave1    (连接到slave1)

    exit          (登出)

    ssh slave2    (连接到slave2)

    exit          (登出)

    ssh slave3    (连接到slave3)

    exit          (登出)

    ssh slave4    (连接到slave4)

    exit          (登出)

    ssh slave5    (连接到slave5)

    exit          (登出)

9.关闭防火墙(6台机器都要关闭,master举例)

    systemctl stop firewalld.service

安装jdk

10.安装jdk之前,先检查是否已经安装了open的jdk,有的话需要先卸载(6台机器都要卸载)

    java -version

11.查看有jdk的存在,需要先卸载然后再安装oracle的jdk

    rpm -qa | grep java      (查询java版本)

    rpm -e --nodeps xxx      (逐个删除完)

    rpm -qa | grep java      (没有显示有了,那就是删除完了,可以安装oracle的jdk)

12.在usr目录下创建java文件夹,将jdk拷贝到java目录

    cd /usr/java

    ls

    tar zxvf jdk-8u144-linux-x64.tar.gz

   ls

13.jdk的环境变量配置(使用的是在root目录下的全局配置文件/etc/profile,6台机器都要配置,master举例)

    vi /etc/profile

    export JAVA_HOME=/usr/java/jdk1.8.0_144

    export PATH=$JAVA_HOME/bin:$PATH

    export JRE_HOME=$JAVA_HOME/jre

    export CLASSPATH=.:$JAVA_HOME/lib:${JRE_HOME}/lib

    保存退出之后使用命令让配置生效

    source /etc/profile

    验证版本

安装zookeeper

14.上传和解压zookeeper解压到/home/kfs目录(在Slave1,2,3,4,5节点上配置)

    cd software/

    ls

    tar -zxvf zookeeper-3.4.5.tar.gz -C /home/kfs/

15.来到解压的zookeeper-3.4.5/conf目录下,将zoo_sample.cfg复制到zoo.cfg

   cd ..

    cd zookeeper-3.4.5/conf/

    ls

    cp zoo_sample.cfg zoo.cfg

16.修改zookeeper的配置

    添加以下配置

dataDir=/home/kfs/zookeeper-3.4.5/data

dataLogDir=/home/kfs/zookeeper-3.4.5/log

clientPort=2181

server.1=Slave1:2888:3888

server.2=Slave2:2888:3888

server.3=Slave3:2888:3888

server.4=Slave4:2888:3888

server.5=Slave5:2888:3888

添加ZK环境变量

/etc/profile

#zookeeper-3.5.7
export ZOOKEEPER_HOME=/home/hadoop/bigdata/zookeeper-3.5.7
export PATH=$PATH:${ZOOKEEPER_HOME}/bin
 

注意:

Client port not found in static config file. 
Looking in dynamic config file. grep: : No such file or directory

搭建zk 环境
Client port not found in static config file. 
Looking in dynamic config file. grep: : No such file or directory

zoo.cfg 版本配置区别
3.4.*和更早版本配置
# example sakes.

dataDir= /Users/zhanghuilong/zkgroup/zk3/data
dataLogDir= /Users/zhanghuilong/zkgroup/zk3/log
clientPort= 2187
server.1= localhost:2887:3887
server.2= localhost:2888:3888
server.3= localhost:2889:3889

3.5.* zoo.cfg 配置
注意点:server 配置后面 多了 “;2187” 对应clientPort

# example sakes.

dataDir= /Users/zhanghuilong/zkgroup/zk3/data
dataLogDir= /Users/zhanghuilong/zkgroup/zk3/log
#clientPort= 2187
server.1= localhost:2887:3887;2187
server.2= localhost:2888:3888;2187
server.3= localhost:2889:3889;2187 

17.创建log和data目录,新建myid加入对应的server.x参数(比如slave1的myid内容是1)每台服务器都需要

    mkdir log

    mkdir data

    echo "1"

安装hadoop

18.安装解压hadoop到/home/kfs目录下(Master举例)

    tar -zxvf hadoop-2.7.4.tar.gz -C /home/kfs/

    解压成功

添加HADOOP环境变量

#hadoop-3.1.3
export HADOOP_HOME=/home/hadoop/bigdata/hadoop-3.1.3
export HADOOP_HDFS_HOME=$HADOOP_HOME
export HADOOP_YARN_HOME=$HADOOP_HOME
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

export HDFS_DATANODE_USER=root
export HDFS_DATANODE_SECURE_USER=root
export HDFS_NAMENODE_USER=root
export HDFS_SECONDARYNAMENODE_USER=root

export YARN_RESOURCEMANAGER_USER=root
export YARN_NODEMANAGER_USER=root
 

19.进入配置文件目录下修改配置文件

    cd hadoop-2.7.4

    cd etc/hadoop

20.修改core-site.xml

    vi core-site.xml

<configuration>

    <!-- 指定hdfs的nameservice为ns1 -->

    <property>

       <name>fs.defaultFS</name>

       <value>hdfs://ns1/</value>

    </property>

    <!-- 指定hadoop临时目录,tmp这个目录需要提前建立好 -->

    <property>

       <name>hadoop.tmp.dir</name>

       <value>/home/data/hadoop-data/tmp</value>

    </property>

    <!-- 指定zookeeper地址 -->

    <property>

       <name>ha.zookeeper.quorum</name>

       <value>Slave1:2181,Slave2:2181,Slave3:2181,Slave4:2181,Slave5:2181</value>

    </property>

</configuration>

21.修改hdfs-site.xml

    vi hdfs-site.xml

<configuration>

    <!--指定hdfs的nameservice为ns1,需要和core-site.xml中的保持一致 -->

    <property>

       <name>dfs.nameservices</name>

       <value>ns1</value>

    </property>

    <!-- ns1下面有两个NameNode,分别是nn1,nn2 -->

    <property>

       <name>dfs.ha.namenodes.ns1</name>

       <value>nn1,nn2</value>

    </property>

    <!-- nn1的RPC通信地址 -->

    <property>

       <name>dfs.namenode.rpc-address.ns1.nn1</name>

       <value>Master:9000</value>

    </property>

    <!-- nn1的http通信地址 -->

    <property>

       <name>dfs.namenode.http-address.ns1.nn1</name>

       <value>Master:50070</value>

    </property>

    <!-- nn2的RPC通信地址 -->

    <property>

       <name>dfs.namenode.rpc-address.ns1.nn2</name>

       <value>Slave1:9000</value>

    </property>

    <!-- nn2的http通信地址 -->

    <property>

       <name>dfs.namenode.http-address.ns1.nn2</name>

       <value>Slave1:50070</value>

    </property>

    <!-- 指定NameNode的元数据在JournalNode上的存放位置 -->

    <property>

       <name>dfs.namenode.shared.edits.dir</name>

    <value>qjournal://Slave1:8485;Slave2:8485;Slave3:8485;Slave4:8485;Slave5:8485;/ns1</value>

    </property>

    <!-- 指定JournalNode在本地磁盘存放数据的位置 -->

    <property>

       <name>dfs.journalnode.edits.dir</name>

       <value>/home/data/hadoop-data/journaldata</value>

    </property>

    <!-- 开启NameNode失败自动切换 -->

    <property>

       <name>dfs.ha.automatic-failover.enabled</name>

       <value>true</value>

    </property>

    <!-- 配置失败自动切换实现方式 -->

    <property>

       <name>dfs.client.failover.proxy.provider.ns1</name>

    <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>

    </property>

    <!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行-->

    <property>

       <name>dfs.ha.fencing.methods</name>

       <value>

           sshfence

           shell(/bin/true)

       </value>

    </property>

    <!-- 使用sshfence隔离机制时需要ssh免登陆 -->

    <property>

       <name>dfs.ha.fencing.ssh.private-key-files</name>

       <value>/home/kfs/.ssh/id_rsa</value>

    </property>

    <!-- 配置sshfence隔离机制超时时间 -->

    <property>

       <name>dfs.ha.fencing.ssh.connect-timeout</name>

       <value>30000</value>

    </property>

</configuration>

22.新增mapred-site.xml

    vi mapred-site.xml

<configuration>

    <!-- 指定mr框架为yarn方式 -->

    <property>

       <name>mapreduce.framework.name</name>

       <value>yarn</value>

    </property>

</configuration>

23.修改yarn-site.xml

    vi yarn-site.xml

<configuration>

    <!-- 开启RM高可用 -->

    <property>

       <name>yarn.resourcemanager.ha.enabled</name>

       <value>true</value>

    </property>

    <!-- 指定RM的cluster id -->

    <property>

       <name>yarn.resourcemanager.cluster-id</name>

       <value>yrc</value>

    </property>

    <!-- 指定RM的名字 -->

    <property>

       <name>yarn.resourcemanager.ha.rm-ids</name>

       <value>rm1,rm2</value>

    </property>

    <!-- 分别指定RM的地址 -->

    <property>

       <name>yarn.resourcemanager.hostname.rm1</name>

       <value>Slave2</value>

    </property>

    <property>

       <name>yarn.resourcemanager.hostname.rm2</name>

       <value>Slave3</value>

    </property>

    <!-- 指定zk集群地址 -->

    <property>

       <name>yarn.resourcemanager.zk-address</name>

       <value>Slave1:2181,Slave2:2181,Slave3:2181,Slave4:2181,Slave5:2181</value>

    </property>

    <property>

       <name>yarn.nodemanager.aux-services</name>

       <value>mapreduce_shuffle</value>

    </property>

</configuration>

24.修改slaves

    vi slaves

Slave1

Slave2

Slave3

Slave4

Slave5

25.修改hadoop-env.sh

    vi hadoop-env.sh

export JAVA_HOME=/usr/java/jdk1.8.0_144

26.修改yarn-env.sh

    vi yarn-env.sh

export JAVA_HOME=/usr/java/jdk1.8.0_144

27. 所有需要修改的配置文件

    (  core-site.xml

       hdfs-site.xml

       mapred-site.xml

       yarn-site.xml

       slaves

       hadoop-env.sh

       yarn-env.sh)

28.将配置好的hadoop拷贝到其他节点

    cd

    scp -r ./hadoop-2.7.4 slave1:/home/kfs/

    scp -r ./hadoop-2.7.4 slave2:/home/kfs/

    scp -r ./hadoop-2.7.4 slave3:/home/kfs/

    scp -r ./hadoop-2.7.4 slave4:/home/kfs/

    scp -r ./hadoop-2.7.4 slave5:/home/kfs/

29.来到root用户配置环境变量

    su root

    vi /etc/profile

export HADOOP_HOME=/home/kfs/hadoop-2.7.4

export PATH=$JAVA_HOME/bin:$PATH:$HADOOP_HOME/bin

30.生效配置文件

    source  /etc/profile

31.回到kfs用户的hadoop目录创建hadoop的临时文件夹和存放hdfs的文件夹

    su kfs

    cd hadoop-2.7.4/

    mkdir tmp

    mkdir journaldata

启动集群

32.启动zookeeper集群(需要启动Slave1,2,3,4,5,以Slave1举例)

    bin/zkServer.sh start       (启动服务)

    bin/zkServer.sh status      (查看服务状态)

33.启动 journalnode(需要启动Slave1,2,3,4,5,以Slave1举例)

    cd

    cd hadoop-2.7.4

    ./sbin/hadoop-daemon.sh start journalnode

34.格式化HDFS(在Matser上执行)(主用)

    ./bin/hdfs namenode -format ns

35. 启动namenode进程

    ./sbin/hadoop-daemon.sh start namenode

36.格式化HDFS(在Slave1上执行)(备用,或者是直接将Master下的/home/data/hadoop-data/tmp复制到Slave1)

    ./bin/hdfs namenode -bootstrapStandby

37. 启动namenode进程

    ./sbin/hadoop-daemon.sh start namenode

38.在两台namenode节点都启动ZKFC

    ./sbin/hadoop-daemon.sh start zkfc

39.启动datanode(需要启动Slave1,2,3,4,5,以Slave1举例)

    ./sbin/hadoop-daemon.sh start datanode

40.启动ResourceManager(在Slave2和Slave3启动)

    ./sbin/start-yarn.sh

41.启动的时候如果只有namenode,应该是VERSION下的cluster的id不匹配。可以将Master下复制到其他节点下

    vi /home/data/hadoop-data/tmp/dfs/name/current/VERSION

注意:start-dfs.sh启动时报错

Hadoop运行startdfs.sh报ERROR: Attempting to operate on hdfs as root错误的解决方法


错误提示:

Starting namenodes on [master]
ERROR: Attempting to operate on hdfs namenode as root
ERROR: but there is no HDFS_NAMENODE_USER defined. Aborting operation.

Starting datanodes
ERROR: Attempting to operate on hdfs datanode as root
ERROR: but there is no HDFS_DATANODE_USER defined. Aborting operation.

Starting secondary namenodes
ERROR: Attempting to operate on hdfs secondarynamenode as root
ERROR: but there is no HDFS_SECONDARYNAMENODE_USER defined. Aborting operation.

Starting journal nodes
ERROR: Attempting to operate on hdfs journalnode as root
ERROR: but there is no HDFS_JOURNALNODE_USER defined. Aborting operation.

Starting ZK Failover Controllers on NN hosts
ERROR: Attempting to operate on hdfs zkfc as root
ERROR: but there is no HDFS_ZKFC_USER defined. Aborting operation.

原因:

使用root账号启动服务,但没预先定义

解决方法:

* 该步骤需要在每台机都执行,也可以先在其中一台机修改,再用scp同步给其它机

1.修改start-dfs.sh和stop-dfs.sh

cd /home/hadoop/sbin
vim start-dfs.sh
vim stop-dfs.sh

在头部添加以下内容:

HDFS_ZKFC_USER=root
HDFS_JOURNALNODE_USER=root
HDFS_NAMENODE_USER=root
HDFS_SECONDARYNAMENODE_USER=root
HDFS_DATANODE_USER=root
HDFS_DATANODE_SECURE_USER=root
#HADOOP_SECURE_DN_USER=root

2.修改start-yarn.sh和stop-yarn.sh

cd /home/hadoop/sbin
vim start-yarn.sh
vim stop-yarn.sh

在头部添加以下内容:

#HADOOP_SECURE_DN_USER=root
HDFS_DATANODE_SECURE_USER=root
YARN_NODEMANAGER_USER=root
YARN_RESOURCEMANAGER_USER=root

3.同步到其它机

cd /home/hadoop/sbin
scp * c2:/home/hadoop/sbin
scp * c3:/home/hadoop/sbin
scp * c4:/home/hadoop/sbin

42.用jps查看一下起的进程是否正确

43.使用管理员方式运行hosts文件

    在其中添加

188.2.11.148  Master

188.2.11.149  Slave1

188.2.11.150  Slave2

188.2.11.151  Slave3

188.2.11.152  Slave4

188.2.11.153  Slave5

44.访问master:50070和slave1:50070可以看出都是namenode,但一个是Active一个是Standby

HADOOP启动顺序:

1、启动ZK所有从节点
 
 zkServer.sh start

2、ceson01主机初次运行需要格式化hdfs,后面运行就不需要步骤

每个hadoop节点启动journalnode
hdfs --daemon start journalnode

# 在主节点 上手动输入[hdfs namenode –format]
hdfs namenode -format

#格式化 zk(在主节点 手动输入)
hdfs zkfc -formatZK

#启动 主节点 namenode 
hadoop-daemon.sh start namenode

#从节占上同步主节点 namenode元数据 
hdfs namenode -bootstrapStandby


3、启动Hadoop集群环境

start-all.sh
或者启动
start-dfs.sh
start-yarn.sh

4、 主备节点启动状况查看

 hdfs haadmin -getServiceState nn1
active
 hdfs haadmin -getServiceState nn2
standby
 
5、 手动启动ZK
 hadoop-daemon.sh start zkfc
 

hadoop-daemon.sh start namenode

hadoop-daemon.sh start datanode

hdfs  -daemon start datanode

hdfs  -daemon start  namenode

一. 非 HDFS HA 集群转换成 HA 集群
1. 分别启动所有的 journalnode 进程,在其中一台 NameNode 上完成即可(比如 NameNode1)

$HADOOP_HOME/sbin/hadoop-daemon.sh start  journalnode

2. 在 NameNode1上对 journalnode 的共享数据进行初始化,然后启动 namenode 进程

$HADOOP_HOME/bin/hdfs namenode -initializeSharedEdits
$HADOOP_HOME/sbin/hadoop-daemon.sh start  namenode

3. 在 NameNode2 上同步 journalnode 的共享数据,和 NameNode 上存放的元数据,然后启动 namenode 进程

$HADOOP_HOME/bin/hdfs namenode  -bootstrapStandby
$HADOOP_HOME/sbin/hadoop-daemon.sh start  namenode

4. 在其中一台 NameNode 上启动所有的 datanode 进程

$HADOOP_HOME/sbin/hadoop-daemon.sh  start datanode


二. HDFS 的 HA 自动切换命令

说明: 为了更加通俗的说明,笔者将两台运行 namenode 进程的主机名抽象为 NameNode1 和 NameNode2,笔者更倾向 NameNode1 上的运行的是 active 状态的 namenode 进程,NameNode2 上的运行的是 standby状态的 namenode 进程,而实际操作中,master5 就是这个 NameNode1 ,master52 就是这个 NameNode2。

抽象主机名    实际操作主机名    初始状态    理想稳定状态
NameNode1    master5    standby    active
NameNode2    master52    standby    standby
2.1 获得当前 NameNode 的 active 和 standby 状态
当未启动 ZK 服务时,发现两个 NameNode 都是 standby 的状态,通过以下命令可以查得:

hdfs haadmin -getServiceState master5
hdfs haadmin -getServiceState master52


2.2 NameNode 的 active 和 standby 状态切换
根据集群是否已经在 hdfs-site.xml 中设置了 dfs.ha.automatic-failover.enabled 为 true (即自动故障状态切换)来分两种情况

1. 未设置自动故障切换 (false)

确定要转为 active 状态的主机名,这里将 NameNode1 设为 active,使用命令行工具进行状态切换:

hdfs haadmin -failover --forcefence --forceactive NameNode2 NameNode1

此处 “NameNode2 NameNode1” 的顺序表示 active 状态由 NameNode2 转换到 NameNode1 上(虽然 NameNode2 在转化前也是 standby 状态)。

有时候,当我们系统中 NameNode2 出现故障了,就可以利用上一步中把 NameNode1 的状态切换为active 后,系统自动把 NameNode2 上的 namenode 进程关闭,再把错误原因排除后重启该 namenode进程,启动后该 namenode 状态为 standby,等待下一次 NameNode1 出现故障时即可将 NameNode2 状态切换为 active。

亦或者使用以下命令将 NameNode1 主机上的 namenode 状态切换到 active 或 standby 状态

hdfs haadmin -transitionToActive NameNode1 
hdfs haadmin -transitionToStandby NameNode1  

但是需要注意的是这两个命令不会尝试运行任何的 fence,因此不应该经常使用。应该更倾向于用 hdfs haadmin -failover 命令。


2. 设置自动故障切换 (true)

如果执行下面命令,则会报错

hdfs haadmin -failover --forcefence --forceactive NameNode2 NameNode1

错误信息:

forcefence and forceactive flags not supported with auto-failover enabled.

若要手工切换其中一个 NameNode 节点的 Active 状态改变为 Standby 状态,将另一个 NameNode 节点的 Standby 状态改变为 Active 状态,则可以 kill -9 <pid of NN> 来杀死当前 Active 状态的 NameNode 上的 namenode 进程号,此时发现另一个 NameNode 节点就由 Standby 状态改变为 Active 状态,这个时候在重启被杀死进程的 NameNode 上的 namenode 进程,此时就成为了 Standby 状态,切换成功!

假设此时 master52 上 namedode 是 active 状态,而 master5 上 namenode 是 standby 状态,下图呈现了该过程:

另外一种方法就是,关闭当前为 active namenode 状态的上的 DFSZKFailoverController 进程(这个方法可靠性有待考察…)

hadoop-daemon.sh stop zkfc

此时,active 状态的 namenode 立刻更变为 standby 状态,另一个 standby 状态的 nameNode 立刻更变为 active 状态,如下图所示:

当继续关闭了另一个 namenode 的 zkfc 服务之后,它依旧是 active 状态,且两个 namenode 仍然正常工作!

在经过上述之后,master5 的 namenode 变为了 standby ,如果通过它提供的命令转化为 active 会怎样?失败了呗,看英文解释吧…

hdfs haadmin -transitionToActive master5
 


更多命令可以通过 help 查看,更多详细解释请看 管理员命令

hdfs haadmin -help


其中 checkHealth 检查 NameNode1 的状态。正常就返回 0,否则返回非 0 值。

hdfs haadmin -checkHealth NameNode1

关键人家官网也说了,这个功能还没有实现,现在将总是返回 success,除非给定的 NameNode 完全关闭。

2.3 HDFS HA自动切换比手工切换多出来的步骤
配置文件 core-site.xml 增加了配置项 ha.zookeeper.quorum(zk集群的配置)

配置文件 hdfs-site.xml 中把 dfs.ha.automatic-failover.enabled 改为true

操作上格式化 zk,执行命令 bin/hdfs zkfc -formatZK

在两个 NameNode 上启动 zkfc,执行命令 sbin/hadoop-daemon.sh start zkfc

三. ResourceManager 的 HA 自动切换命令

说明: 为了更加通俗的说明,笔者将两台运行 resourcemanager 进程的主机名抽象为 RM1 和 RM2,笔者更倾向 RM1 上的运行的是 active 状态的 resourcemanager 进程,RM2 上的运行的是 standby 状态的 resourcemanager 进程,而实际操作中,master5 就是这个 RM1 ,master52 就是这个 RM2。

抽象主机名    实际操作主机名    初始状态    理想稳定状态    ha-id
RM1    master5    active    active    rm1
RM2    master52    standby    standby    rm2

其中关于 ha-id 是在 yarn-site.xml 配置文件中设置的。

hadoop也为管理员提供了 CLI 的方式管理 RM HA,但在没有启用 HA 的情况下,也就是在 yarn-site.xml 配置文件中没有设置 yarn.resourcemanager.ha.enabled 为 true 时 (默认为false,不启用),下面的命令是不可用的。

3.1 获得当前 RM 的 active 和 standby 状态
yarn rmadmin -getServiceState rm1
yarn rmadmin -getServiceState rm2

3.2 RM 的 active 和 standby 状态切换
根据集群是否已经在 yarn-site.xml 中设置了 yarn.resourcemanager.ha.automatic-failover.enabled 为 true (即自动故障状态切换)来分两种情况

1. 未设置自动故障切换 (false)

yarn rmadmin -transitionToStandby rm1
yarn rmadmin -transitionToActive rm2

2. 设置自动故障切换 (true)

yarn rmadmin -transitionToStandby rm1
yarn rmadmin -transitionToActive rm2
 


显而易见,失败了。如果需要手工切换,这时候可以

kill -9 <pid of RM> 杀掉 active 状态的 RM 的 resourcemanager 进程
或关闭 active 状态的 RM 的 resourcemanager 进程
yarn-daemon.sh stop resourcemanager
然后再重启 RM 的 resourcemanager 进程

yarn-daemon.sh start resourcemanager
此时就可以成功切换状态了…

3.3 yarn rmadmin 所支持的命令
更多命令可以通过 help 查看

yarn rmadmin -help


其中列出的 -failover 选项,yarn rmadmin 不支持此选项。更多详细解释请看 使用 yarn rmadmin 管理 ResourceManager HA

3.4 YARN HA自动切换比手工切换多出来的步骤
配置文件 yarn-site.xml 中把 yarn.resourcemanager.ha.automatic-failover.enabled 改为 true。该属性的含义是:是否启用自动故障转移。默认情况下,在启用 HA 时,启用自动故障转移
配置文件 yarn-site.xml 中把 yarn.resourcemanager.ha.automatic-failover.embedded 改为 true。启用内置的自动故障转移。默认情况下,在启用 HA 时,启用内置的自动故障转移


四. HDFS HA 故障切换后欲恢复原 active NameNode 步骤
假设原本是 active NameNode 的 master5 的主机因为某种突发情况而失效了,此时之前处于 standby 的 master52 变为了 active 继续承担 namenode 的责任。 一段时间后, master5 恢复正常了,但只能是 standby 的状态。这时若想将 master5 恢复成 active ,该如何做呢?以下是笔者自己总结的,准确性有待商榷…

在 Journal 和 QuorumPeerMain 进程正常启动的情况下

将所有的 datanode 进程关闭,将 master5 上的 namenode 进程也关闭
在 master5 上执行 hdfs namenode -bootstrapStandby
再将 master52 上重启 namenode 进程, OK 了
 

安装hbase

45.解压Hbase到hbase(master举例,别的节点再拷贝过去就行)

    cd software

    ls

    tar -zxvf hbase-1.2.3-bin.tar.gz -C /home/kfs

46.来到/home/data目录下创建hbase-data存放hbase的数据

    mkdir hbase-data

    cd hbse-data

    mkdir logs

    mkdir pids

47.修改hbase-env.sh

    vi hbase-env.sh


export JAVA_HOME=/opt/jdk1.8.0_191
export HADOOP_HOME=/database/hadoop/bigdata/hadoop-3.1.3
export HBASE_LOG_DIR=/database/data/hbase-data/logs
export HBASE_PID_DIR=/database/data/hbase-data/pids
export HBASE_MANAGES_ZK=false
 

48.修改hbase-site.xml

    vi hbase-site.xml

<configuration>

  <!-- 指定hbase在HDFS上存储的路径 -->

  <property> 

     <name>hbase.rootdir</name>

     <value>hdfs://master:9000/hbase</value>

  </property>

  <!-- 指定hbase是分布式的 -->

  <property>

     <name>hbase.cluster.distributed</name>

     <value>true</value>

  </property>

  <!-- 指定zk的地址,多个用“,”分割 -->

  <property>

    <name>hbase.zookeeper.quorum</name>

    <value>slave1,slave2,slave3,slave4,slave5</value>

  </property>

  <!--本地系统的临时文件夹(/tmp会在重启时清除) -->

  <property>

    <name>hbase.tmp.dir</name>

    <value>/home/data/hbase-data/tmp</value>

  </property>

  <!--zookeeper中zoo.cfg的dataDir路径-->

  <property>

    <name>hbase.zookeeper.property.dataDir</name>

    <value>/home/kfs/zookeeper-3.4.5/data</value>

  </property>

  <!--zookeeper会话超时,hbase把值传递给zk集群,向它推荐一个会话的最大超时时间-->

  <property>

    <name>zookeeper.session.timeout</name>

    <value>120000</value>

  </property>

</configuration>

49.修改regionservers

    vi regionservers

    Slave1

    Slave2

    Slave3

    Slave4

    Slave5

50.复制hadoop下的core-site.xml和hdfs-site.xml文件到hbase的conf下

    cp /home/kfs/hadoop-2.7.4/etc/hadoop/core-site.xml /home/kfs/hbase-1.2.3/conf/

    cp /home/kfs/hadoop-2.7.4/etc/hadoop/hdfs-site.xml /home/kfs/hbase-1.2.3/conf/

51.拷贝新建的文件夹到别的节点上

    scp -r /home/data/hbase-data/ slave1:/home/data/hbase-data/

    scp -r /home/data/hbase-data/ slave2:/home/data/hbase-data/

    scp -r /home/data/hbase-data/ slave3:/home/data/hbase-data/

    scp -r /home/data/hbase-data/ slave4:/home/data/hbase-data/

    scp -r /home/data/hbase-data/ slave5:/home/data/hbase-data/

52.拷贝hbase的文件夹到别的节点

    scp -r /home/kfs/hbase-1.2.3/ slave1:/home/kfs/hbase-1.2.3/

    scp -r /home/kfs/hbase-1.2.3/ slave2:/home/kfs/hbase-1.2.3/

    scp -r /home/kfs/hbase-1.2.3/ slave3:/home/kfs/hbase-1.2.3/

    scp -r /home/kfs/hbase-1.2.3/ slave4:/home/kfs/hbase-1.2.3/

    scp -r /home/kfs/hbase-1.2.3/ slave5:/home/kfs/hbase-1.2.3/

53.来到root用户修改环境变量

    su root

    vi /etc/profile

    export HBASE_HOME=/home/kfs/hbase-1.2.3

    :$HBASE_HOME/bin

    让配置生效

54.返回kfs用户启动主HMaster

    su kfs

    cd ..

    ./bin/start-hbase.sh

start-hbase.sh note:如果有log4j错误 每个hbase安装的节点执行以下脚本删除jar rm -rf /home/ceson/wechat_env/hbase-2.0.5/lib/slf4j-log4j12-1.7.25.jar 

55.启动Slave1作为备份的HMaster

    ./bin/hbase-daemon.sh start master

56.如果启动时有个别节点没有启动HRegionserver,则单独启动

    ./hbase-daemon.sh start regionserver

57.如果还是自动关闭,查看是不是时间差别大,可以同步时间,或者是在hbase的hbase-site.xml配置文件下添加,将时间改大点

<property>

    <name>hbase.master.maxclockskew</name>

    <value>150000</value>

</property>

登录6台机器,执行
jps
master节点机器有以下进程
28117 HMaster

备用节点
31281 HMaster
31131 HRegionServer

其它节点
29371 HRegionServer

或者访问
http://ip:16010

打开页面测试查看高可用是否启用
http://ceson02:16010

 

58.通过浏览器访问hbase管理页面

    Master:16010

    Slave1:16010

安装hive

59.安装hive之前先安装MySQL,要使用MySQL做元数据,但在安装MySQL之前先删除mariadb

    rpm -qa |grep -i mariadb        (查看是否有mariadb)

60.存在mariadb则卸载

    rpm -e --nodeps mariadb-libs-5.5.56-2.el7.x86_64

61. 判断mysql是否存在,有则删除

    rpm -qa |grep -i mysql      (查看mysql是否存在)

62.来到software目录下的mysql8.0文件夹安装mysql

    cd software/mysql-8.0

    rpm  -ivh  mysql-community-common-8.0.11-1.el7.x86_64.rpm

    rpm  -ivh  mysql-community-libs-8.0.11-1.el7.x86_64.rpm

    rpm  -ivh  mysql-community-client-8.0.11-1.el7.x86_64.rpm

    rpm  -ivh  mysql-community-server-8.0.11-1.el7.x86_64.rpm

63.启动mysql的服务

    service mysqld start

64.查看初始密码

    vi  /var/log/mysqld.log

    初始密码是_#?1j&OjVp=E

65.登录mysql

    mysql -u root -p

    输入密码:_#?1j&OjVp=E

66.修改mysql的root密码(注:密码需要有8位,包含数字,小写字母,大写字母,特殊符号)

    alter user 'root'@'localhost' identified by '1qaz@WSX';

67.创建一个hive的用户并设置权限

create user 'hive'@'%' identified by '1qaz@WSX';

grant all privileges on *.* to 'hive'@'%' with grant option;

flush privileges;

68.返回kfs用户解压hive到kfs目录下

    quit       (退出mysql界面)

    exit       返回kfs用户

    cd software  

    tar -zxvf apache-hive-2.3.2-bin.tar.gz -C /home/kfs/

69.来到hive目录的conf文件夹下,新增hive-site.xml,设置元数据库等

    cd

    ls

    cd apache-hive-2.3.2-bin/conf/

    vi hive-site.xml

<configuration>

        <property>

          <name>hive.metastore.schema.verification</name>

          <value>false</value>

        </property>

    <!--JDBC元数据仓库连接字符串-->

        <property>

          <name>javax.jdo.option.ConnectionURL</name>

          <value>jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true</value>

          <description>JDBC connect string for a JDBC metastore</description>

        </property>

       <!--JDBC元数据仓库驱动类名-->

       <property>

          <name>javax.jdo.option.ConnectionDriverName</name>

          <value>com.mysql.cj.jdbc.Driver</value>

          <description>Driver class name for a JDBC metastore</description>

        </property>

    <!--元数据仓库用户名-->

        <property>

          <name>javax.jdo.option.ConnectionUserName</name>

          <value>root</value>

          <description>username to use against metastore database</description>

        </property>

    <!--元数据仓库密码-->

        <property>

          <name>javax.jdo.option.ConnectionPassword</name>

          <value>1qaz@WSX</value>

          <description>password to use against metastore database</description>

        </property>

        <property>

          <name>datanucleus.readOnlyDatastore</name>

          <value>false</value>

        </property>

        <property>

          <name>datanucleus.fixedDatastore</name>

          <value>false</value>

        </property>

        <property>

          <name>datanucleus.autoCreateSchema</name>

          <value>true</value>

        </property>

        <property>

          <name>datanucleus.autoCreateTables</name>

          <value>true</value>

        </property>

        <property>

          <name>datanucleus.autoCreateColumns</name>

          <value>true</value>

        </property>

        <property>

          <name>hive.exec.local.scratchdir</name>

          <value>/home/kfs/apache-hive-2.3.2-bin/iotmp</value>

          <description>Local scratch space for Hive jobs</description>

        </property>

         <property>

          <name>hive.querylog.location</name>

          <value>/home/kfs/apache-hive-2.3.2-bin/iotmp/</value>

          <description>Location of Hive run time structured log file</description>

        </property>

        <property>

          <name>hive.downloaded.resources.dir</name>

          <value>/home/kfs/apache-hive-2.3.2-bin/iotmp/</value>

          <description>Temporary local directory for added resources in the remote file system.</description>

        </property>

</configuration>

70.将mysql-connector-java-8.0.11.jar复制到hive的lib目录下

    cp /home/kfs/software/mysql-8.0/mysql-connector-java-8.0.11.jar /home/kfs/apache-hive-2.3.2-bin/lib/

71.修改环境变量

    vi /etc/profile

    export HIVE_HOME=/home/kfs/apache-hive-2.3.2-bin

    :$HIVE_HOME/bin:$HIVE_HOME/conf

生效配置文件

72.返回kfs用户并返回hive目录

    exit

    cd ..

73.启动hive的metastore

    ./bin/hive --service metastore &

74.启动hive的hiveserver2

    ./bin/hive --service hiveserver2&

75.查看jps有两个RunJar就可以了

76.启动hive

    ./bin/hive           (方式一)

    ./bin/hive  -hiveconf  hive.root.logger=DEBUG,console(方式二,启动这个可以打印出各种log) 

安装Flume

77.解压flume到/home/kfs/   (以Slave1举例,其他的节点拷贝,并修改环境变量)

    cd software

    tar -zxvf apache-flume-1.8.0-bin.tar.gz -C /home/kfs/

78.来到flume的conf目录下复制两个文件

    cd apache-flume-1.8.0-bin/conf/

    cp flume-env.sh.template flume-env.sh

79.修改flume-env.sh文件

    vi flume-en.sh

export JAVA_HOME=/usr/java/jdk1.8.0_144

export JAVA_OPTS="-Xms100m -Xmx2000m -Dcom.sun.management.jmxremote"

80.配置一个配置文件作为测试,flume-conf.properties

    vi flume-conf.properties

a1.sources = r1

a1.sinks = k1

a1.channels = c1

a1.sources.r1.type = netcat

a1.sources.r1.bind = localhost

a1.sources.r1.port = 44444

a1.sources.r1.channels = c1

a1.sinks.k1.type = logger

a1.sinks.k1.channel = c1

a1.channels.c1.type = memory

a1.channels.c1.capacity = 1000

a1.channels.c1.transactionCapacity = 100

81.来到root用户修改环境变量

    su root

    vi /etc/profile

export FLUME_HOME=/home/kfs/apache-flume-1.8.0-bin

export FLUME_CONF_DIR=$FLUME_HOME/conf

:FLUME_HOME/bin

生效配置

source /etc/profile

82.将flume文件夹拷贝到其他节点

    scp -r /home/kfs/apache-flume-1.8.0-bin/ slave2:/home/kfs/

    scp -r /home/kfs/apache-flume-1.8.0-bin/ slave3:/home/kfs/

    scp -r /home/kfs/apache-flume-1.8.0-bin/ slave4:/home/kfs/

    scp -r /home/kfs/apache-flume-1.8.0-bin/ slave5:/home/kfs/

83.启动flume

   

./bin/flume-ng agent --conf ./conf/ --conf-file ./conf/flume-conf.properties --name a1 -Dflume.root.logger=INFO,console

启动成功

安装kafka

84.解压kafka到/home/kfs/   (以Slave1举例,其他的节点拷贝,并修改环境变量)

    cd software

    tar -zxvf kafka_2.11-0.10.0.0.tgz -C /home/kfs/

85.来到kafka的config目录修改server配置文件

    cd kafka_2.11-0.10.0.0/config/

    vi server.properties

86.修改server.properties配置文件

broker.id=0

host.name=188.2.11.149

port=9092

log.dirs=/home/data/kafka-data/log-0

zookeeper.connect=localhost:2181

87.将其他kafka的文件夹拷贝到其他节点

scp -r /home/kfs/kafka_2.11-0.10.0.0/ slave2:/home/kfs/

scp -r /home/kfs/kafka_2.11-0.10.0.0/ slave3:/home/kfs/

scp -r /home/kfs/kafka_2.11-0.10.0.0/ slave4:/home/kfs/

scp -r /home/kfs/kafka_2.11-0.10.0.0/ slave5:/home/kfs/

88.修改其他的配置文件

修改slave2的server.properties

修改slave3的server.properties

修改slave4的server.properties

修改slave5的server.properties

89.启动kakfa服务(分别启动5台,以slave1举例)

./bin/kafka-server-start.sh config/server.properties &

启动成功

安装spark

 开始安装Spark3.0.1
上传解压到指定文件夹

2.2.1 配置系统变量:
# spark 3.0.1配置
export  SPARK_HOME=/opt/apps/spark-3.0.1-bin-hadoop3.2
export  PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin

2.2.2 修改配置文件
将所有.template文件复制一份出来,去掉后缀名:

for i in *.template; do cp ${i} ${i%.*}; done

再建立一个目录将原文件移到里面

修改spark-env.sh 加入:

vim spark-env.sh
#加入以下配置
export JAVA_HOME=/home/apps/jdk1.8.0_212
export HADOOP_CONF_DIR=/opt/apps/hadoop-3.2.1/etc/hadoop
export SPARK_MASTER_HOST=linux01.pub
export SPARK_MASTER_PORT=7077
export SPARK_LOCAL_DIRS=/opt/apps/spark-3.0.1-bin-hadoop3.2
在slaves中加入:

linux01.pub
linux02.pub
linux03.pub
linux04.pub
linux05.pub
linux06.pub

2.2.3 分发到其它5台电脑上
 scp -r /opt/apps/spark-3.0.1-bin-hadoop3.2/ linux02.pub:$PWD
scp -r /opt/apps/spark-3.0.1-bin-hadoop3.2/  linux03.pub:$PWD
scp -r /opt/apps/spark-3.0.1-bin-hadoop3.2/  linux04.pub:$PWD
scp -r /opt/apps/spark-3.0.1-bin-hadoop3.2/  linux05.pub:$PWD
scp -r /opt/apps/spark-3.0.1-bin-hadoop3.2/  linux06.pub:$PWD
scp -r /opt/apps/spark-3.0.1-bin-hadoop3.2/  linux06.pub:$PWD

2.2.4 运行spark:
进入spark目录下的sbin下,

./start-all.sh

为了区分开hadoop 中的start-all.sh 可以将此名改个名称,以后用这个名称来启动就不会和hadoop相互冲突了,但实际也很少同时都启动,平时hadoop也只是启动其中的hdfs,即start-dfs.sh而已

 cp start-all.sh  spark-start-all.sh

此时每一台分机上都启动了一个worker进程

网页查看:http://linux01.pub:8080/

至此,spark搭建就已经完成了,相对比较简单。
 

102.查看master:8080

    http://master:8080/

安装Sqoop

103.解压sqoop到/home/kfs目录下(Slave1)

    tar -zxvf sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz -C /home/kfs/

104.重命名sqoop,将名称改简短一点

    mv sqoop-1.4.7.bin__hadoop-2.6.0/ sqoop-1.4.4

105.来到conf下将sqoop-env-template.sh复制成sqoop-env.sh

    cd sqoop-1.4.7/conf/

    cp sqoop-env-template.sh  sqoop-env.sh

106.修改sqoop-env.sh

    vi sqoop-env.sh

export HADOOP_COMMON_HOME=/home/kfs/hadoop-2.7.4

export HADOOP_MAPRED_HOME=/home/kfs/hadoop-2.7.4

    source sqoop-env.sh

107.返回将sqoop-1.4.7.ar复制到 $HADOOP_HOME/share/hadoop/mapreduce/

    cd..

    ls

    cp sqoop-1.4.7.jar  $HADOOP_HOME/share/hadoop/mapreduce/

来到$HADOOP_HOME/share/hadoop/mapreduce/看看有没有

    cd $HADOOP_HOME/share/hadoop/mapreduce/

    ls

108.将JDBC.jar包拷贝到sqlserver和MySQL分别需要用到的jar包拷贝至lib下(自己选择拷贝什么jar)

    cd

    cd sqoop-1.4.4/lib/

    cp /home/kfs/software/sqljdbc4.jar ./

    cp /home/kfs/software/mysql-connector-java-8.0.11.jar ./

    ls

109.来到root修改环境变量

    su root

    vi /etc/profile

    export SQOOP_HOME=/home/kfs/sqoop-1.4.7

    :$SQOOP_HOME/bin

    source /etc/profile

安装Phoenix

110.去到software目录将phoenix解压到/home/kfs(Slave1节点安装)

    cd software/

   

111.将phoenix目录下的其中三个jar复制到所有节点的hbase的lib目录下

    scp phoenix-4.14.1-HBase-1.2-client.jar Slave2:/home/kfs/hbase-1.2.3/lib/

    scp phoenix-4.14.1-HBase-1.2-server.jar Slave2:/home/kfs/hbase-1.2.3/lib/

    scp phoenix-core-4.14.1-HBase-1.2.jar Slave2:/home/kfs/hbase-1.2.3/lib/

112.将hbase中conf下的hbase-site.xml复制到phoenix的bin覆盖掉原有的配置文件

    cp /home/kfs/hbase-1.2.3/conf/hbase-site.xml ./bin/hbase-site.xml

    cd bin/

    ls

113.去到root用户修改环境变量

    su root

    vi /etc/profile

export PHOENIX_HOME=/home/kfs/apache-phoenix-4.14.1-HBase-1.2-bin

export PHOENIX_CLASSPATH=$PHOENIX_HOME

:$PHOENIX_HOME/bin

    source /etc/profile

114.为psql和sqlline赋予权限

    chmod 777 psql.py

    chmod 777 sqlline.py

115.返回到kfs用户,将hdfs集群的配置文件core和hdfs复制到phoenix的bin目录下

    exit

    cp /home/kfs/hadoop-2.7.4/etc/hadoop/core-site.xml ./

    cp /home/kfs/hadoop-2.7.4/etc/hadoop/hdfs-site.xml ./

    ls

116.启动phoenix测试

    ./sqlline.py slave1,slave2,slave3,slave4,slave5:2181

!tables    查看所有数据表,!exit退出

安装Storm

117.解压Storm到/home/kfs目录下

    tar zxvf apache-storm-1.2.2.tar.gz -C /home/kfs/

118.修改storm.yaml

    cd

    ls

    cd apache-storm-1.2.2/conf/

    vi storm.yaml

storm.zookeeper.servers:

     - "Slave1"

     - "Slave2"

     - "Slave3"

     - "Slave4"

     - "Slave5"  

 storm.local.dir: "/home/data/storm-data/tmp"

 nimbus.seeds: ["Slave4", "Slave5"]

 supervisor.slots.ports:

     - 6700

     - 6701

     - 6702

     - 6703

119.创建文件夹(Slave1, Slave2, Slave3, Slave4, Slave5节点都需要创建,Slave5举例)

    cd /home/data/

    mkdir storm-data

    ls

    cd storm-data

    mkdir tmp

120.来到root用户修改环境变量

    su root

    vi /etc/profile

    export STORM_HOME=/home/kfs/apache-storm-1.2.2

    :$STORM_HOME/bin

    source /etc/profile  (让配置生效)

121.返回kfs用户

    exit

122.将storm复制到其他的节点

    scp -r /home/kfs/apache-storm-1.2.2/ slave1:/home/kfs/

    scp -r /home/kfs/apache-storm-1.2.2/ slave2:/home/kfs/

    scp -r /home/kfs/apache-storm-1.2.2/ slave3:/home/kfs/

    scp -r /home/kfs/apache-storm-1.2.2/ slave4:/home/kfs/

123.先启动storm的nimbus再启动supervisor

124.对nimbus的主备节点启动(Slave5, Slave4节点上执行)

    nohup sh storm nimbus &

125.对nimbus主节点启动(Slave5)

    nohup sh storm ui &

126.对supervisor节点启动(Slave1,Slave2,Slave3,Slave4启动)

    nohup sh storm supervisor &

127.执行logviewer(Slave1,Slave2,Slave3,Slave4,Slave5都启动)

    nohup sh storm logviewer &

128.查看所有的节点的jps看是否启动成功

 

 

129. 启动网页查看状态

    Slave5:8080

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/605493
推荐阅读
相关标签
  

闽ICP备14008679号