Hadoop集群搭建及测试

Hadoop集群搭建

1 Hadoop运行模式

Hadoop运行模式包括:本地模式、伪分布式模式以及完全分布式模式。

Hadoop官方网站

Hadoop的运行模式介绍:

  • 本地模式

    hadoop默认安装后启动就是本地模式,就是将来的数据存在Linux本地,并且运行MR程序的时候也是在本地机器上运行

  • 伪分布式模式

    伪分布式其实就只在一台机器上启动HDFS集群,启动YARN集群,并且数据存在HDFS集群上,以及运行MR程序也是在YARN上运行,计算后的结果也是输出到HDFS上。本质上就是利用一台服务器中多个java进程去模拟多个服务

  • 完全分布式

    完全分布式其实就是多台机器上分别启动HDFS集群,启动YARN集群,并且数据存在HDFS集群上的以及运行MR程序也是在YARN上运行,计算后的结果也是输出到HDFS上。

1.1 本地运行模式

本地运行模式(官方wordcount)-- 入门(Hadoop的默认的运行模式)

任务:统计文本中单词出现次数

  1. hadoop-3.1.3文件目录下面创建一个wcinput的文件
mkdir wcinput
  1. wcinput下创建一个word.txt文件
cd input
vim word.txt #或者touch word.txt

在文件中输入一些文字内容

hadoop hadoop
hdfs hdfs hdfs yarn
mapreduce
map reduce
hdfs yarn
spark
  1. 回到hadoop-3.1.3文件目录下,执行程序
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount ./input ./output
  1. 查看结果
cat output/part-r-00000

1.2 完全分布式模式

准备工作:

  1. 准备三台客户机(静态ip、主机名称)
  2. 安装JDK,Hadoop,并配置环境变量
  3. 配置集群
  4. 单点启动
  5. 配置ssh
  6. 群起并测试集群
1.2.1 准备三台虚拟机

准备完全分布式需要的机器: hadoop102 hadoop103 hadoop104

将克隆出来的虚拟机修改静态ip,主机名称。[见 3.2](#3.2 准备hadoop102 机器(通过克隆模板机的方式创建))

1.2.2 编写集群分发脚本xsync
scp(secure copy)安全拷贝
  • 定义:scp可以实现服务器与服务器之间的数据拷贝

  • 基本语法:

scp  -r   $pdir/$fname          $user@hadoop$host:$pdir/$fname
命令 递归   要拷贝的文件路径/名称     目的用户@主机:目的路径/名称
  • 案例实操

前提:在hadoop102 hadoop103 hadoop104 都创建好的/opt.module /opt/software两个文件目录,并且已经把这两个目录修改为xu1an:xu1an

sudo chown xu1an:xu1an -R /opt/module /opt/software
  • 特点:完全拷贝内容,不做任何比较,如果目的地已有相关内容,它会进行覆盖
  1. hadoop102的数据(jdk、hadoop安装目录同步,环境变量文件)同步到 hadoop103 hadoop104

    (注意需要移除/opt/module/hadoop-3.1.3/share下的doc文件,由于doc文件较大)

    cd /opt/module/hadoop-3.1.3/share
    rm -rf doc
    
  2. 集群分发

    • a. 将hadoop102/opt/module 所有目录拷贝到 hadoop103/opt/module

      scp -r ./* xu1an@hadoop103:/opt/module
      
    • b. 在hadoop104上执行:将hadoop102的内容 拉取到hadoop104的指定位置

      scp -r xu1an@hadoop102:/opt/module/jdk1.8.0_212 /opt/module/
      
    • c.在hadoop103上执行:将hadoop102的内容 发送给 hadoop104

      scp -r xu1an@hadoop102:/opt/module/hadoop-3.1.3 xu1an@hadoop104:/opt/module
      
rsync远程同步工具

rsync主要用于备份和镜像。具有速度快、避免复制相同内容和支持符号链接的优点。

rsync和scp区别:用rsync做文件的复制要比scp的速度快,rsync只对差异文件做更新。scp是把所有文件都复制过去。

  • 基本语法:
rsync   -av      $pdir/$fname        $user@hadoop$host:$pdir/$fname
 命令  参数选项  要拷贝的文件路径/名称       目的用户@主机:目的路径/名称  
  • 选项参数说明
选项功能
-a归档拷贝
-v显示复制过程
  • 特点:速度快,不会对重复文件进行拷贝

a. 将hadoop102上的/opt/software/jdk-8u212-linux-x64.tar.gz同步给hadoop103

rsync -av /opt/software/jdk-8u212-linux-x64.tar.gz xu1an@hadoop103:/opt/software/

b. 将hadoop102上的/opt/software/*同步给hadoop103

rsync -av /opt/software/* xu1an@hadoop103:/opt/software

c.在hadoop104上主动向hadoop102拉取/opt/software/*

rsync -av xu1an@hadoop102:/opt/software/* /opt/software/

**注意:**rsync 限制同步数据的时候只能有两台机器进行通信。(不能通过第三台机器进行同步数据)

集群分发脚本
  • 需求:循环复制文件到所有节点的相同目录下

  • 说明:在/home/xu1an/bin这个目录下存放的脚本,xu1an用户可以在系统任何地方直接执行

  1. /home/xu1an/bin目录下创建my_rsync文件

    #可以用echo $PATH查看系统变量
    cd /home/xu1an #此时该目录下并无bin目录,需要创建bin
    echo $PATH #可以发现Linux系统在创建xu1an用户后,为用户添加了/home/xu1an/bin系统变量地址
    mkdir bin
    cd bin
    touch my_rsync
    chmod 744 my_rsync.sh #更改文件权限
    
  2. 在该文件编写如下代码

    #!/bin/bash
    
    #参数预处理
    if [ $# -lt 1 ]
    then
     echo "参数不能为空!!!"
     exit
    fi
    
    #遍历集群中的机器一次分发内容
    for host in hadoop103 hadoop104
    do
      echo "===============$host================"
      #依次分发内容
      for file in $@
      do
       #判断当前文件是否存在
        if [ -e $file ]
        then
         #存在
          #1.获取当前文件目录结构
          pdir=$(cd -P $(dirname $file);pwd)
          #2.获取当前文件名
          fname=$(basename $file)
          #3. 登录目标机器,创建统一的目录结构
          ssh $host "mkdir -p $pdir"
          #4.依次把要分发的文件或者目录进行分发
          rsync -av $pdir/$fname $host:$pdir
        else
         #不存在
         echo "$file文件不存在!!!"
         exit
        fi
      done
    done
    

    测试分发脚本

    my_rsync /home/xu1an/bin/my_rsnyc.sh
    
    1. 集群分发/etc/profile.d/my_env.sh

      由于etc目录下需要root用户权限才能操作。在hadoop102中分发my_env.shhadoop103

      scp -r /etc/profile.d/my_env.sh root@hadoop103:/etc/profile.d  #输入root用户的密码
      

      hadoop103中需要激活该脚本

      source /etc/profile
      

      查看是否生效

      java -version
      hadoop version
      

2.3 hadoop集群部署配置

2.3.1 集群部署规划
	hadoop102    namenode           datanode    nodemanager
	
	hadoop103    resourcemanager    datanode    nodemanager
	 
	hadoop104    secondarynamenode  datanode    nodemanager

注意:NameNodeSecondaryNameNode不要安装在同一台服务器

注意:ResourceManager也很消耗内存,不要和NameNodeSecondaryNameNode配置在同一台机器上。

hadoop102hadoop103hadoop104
HDFSNameNode DataNodeDataNodeSecondaryNameNode DataNode
YARNNodeManagerResourceManager NodeManagerNodeManager
1.3.2 配置文件说明

Hadoop配置文件分两类:默认配置文件和自定义配置文件,只有用户想修改某一默认配置值时,才需要修改自定义配置文件,更改相应属性值。

(1)默认配置文件:

要获取的默认文件文件存放在Hadoop的jar包中的位置
[core-default.xml]hadoop-common-3.1.3.jar/core-default.xml
[hdfs-default.xml]hadoop-hdfs-3.1.3.jar/hdfs-default.xml
[yarn-default.xml]hadoop-yarn-common-3.1.3.jar/ yarn-default.xml
[mapred-default.xml]hadoop-mapreduce-client-core-3.1.3.jar/mapred-default.xml

(2)自定义配置文件:

core-site.xmlhdfs-site.xmlyarn-site.xmlmapred-site.xml四个配置文件存放在$HADOOP_HOME/etc/hadoop这个路径上,用户可以根据项目需求重新进行修改配置。

  • hadoop-env.sh (主要映射jdk的环境变量)(可以不配)

  • core-site.xml (配置hadoop的全局信息)

  • hdfs-site.xml

  • mapread-site.xml

  • yarn-site.xml

注意:Hadoop 中加载配置文件的顺序

​ 当Hadoop集群启动后,先加载默认配置,然后再加载自定义配置文件,自定义的配置信息会覆盖默认配置。

(3)常用端口号说明

DaemonAppHadoop2Hadoop3
NameNode PortHadoop HDFS NameNode8020 / 90009820
Hadoop HDFS NameNode HTTP UI500709870
Secondary NameNode PortSecondary NameNode500919869
Secondary NameNode HTTP UI500909868
DataNode PortHadoop HDFS DataNode IPC500209867
Hadoop HDFS DataNode500109866
Hadoop HDFS DataNode HTTP UI500759864
1.3.3 配置集群

(1)核心配置文件

配置core-site.xml

cd $HADOOP_HOME/etc/hadoop
vim core-site.xml

文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<configuration>
	<!-- 指定NameNode的地址 -->
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://hadoop102:9820</value>
</property>
<!-- 指定hadoop数据的存储目录 -->
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/opt/module/hadoop-3.1.3/data</value>
</property>

<!-- 配置HDFS网页登录使用的静态用户为xu1an -->
    <property>
        <name>hadoop.http.staticuser.user</name>
        <value>xu1an</value>
</property>

<!-- 配置该xu1an(superUser)允许通过代理访问的主机节点 -->
    <property>
        <name>hadoop.proxyuser.xu1an.hosts</name>
        <value>*</value>
</property>
<!-- 配置该xu1an(superUser)允许通过代理用户所属组 -->
    <property>
        <name>hadoop.proxyuser.xu1an.groups</name>
        <value>*</value>
</property>
<!-- 配置该xu1an(superUser)允许通过代理的用户-->
    <property>
        <name>hadoop.proxyuser.xu1an.groups</name>
        <value>*</value>
</property>

</configuration>

(2)HDFS配置文件

配置hdfs-site.xml

vim hdfs-site.xml

文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<configuration>
	<!-- nn web端访问地址-->
	<property>
        <name>dfs.namenode.http-address</name>
        <value>hadoop102:9870</value>
    </property>
	<!-- 2nn web端访问地址-->
    <property>
        <name>dfs.namenode.secondary.http-address</name>
        <value>hadoop104:9868</value>
    </property>
</configuration>

(3)YARN配置文件

配置yarn-site.xml

vim yarn-site.xml

文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<configuration>
	<!-- 指定MR走shuffle -->
    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
</property>
<!-- 指定ResourceManager的地址-->
    <property>
        <name>yarn.resourcemanager.hostname</name>
        <value>hadoop103</value>
</property>
<!-- 环境变量的继承 -->
    <property>
        <name>yarn.nodemanager.env-whitelist</name>
        <value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME</value>
</property>
<!-- yarn容器允许分配的最大最小内存 -->
    <property>
        <name>yarn.scheduler.minimum-allocation-mb</name>
        <value>512</value>
    </property>
    <property>
        <name>yarn.scheduler.maximum-allocation-mb</name>
        <value>4096</value>
</property>
<!-- yarn容器允许管理的物理内存大小 -->
    <property>
        <name>yarn.nodemanager.resource.memory-mb</name>
        <value>4096</value>
</property>
<!-- 关闭yarn对物理内存和虚拟内存的限制检查 -->
    <property>
        <name>yarn.nodemanager.pmem-check-enabled</name>
        <value>false</value>
    </property>
    <property>
        <name>yarn.nodemanager.vmem-check-enabled</name>
        <value>false</value>
    </property>
</configuration>

(4)MapReduce配置文件

配置mapred-site.xml

vim mapred-site.xml

文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<configuration>
	<!-- 指定MapReduce程序运行在Yarn上 -->
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
</configuration>
1.3.4 分发Hadoop配置文件
my_rsync.sh /opt/module/hadoop-3.1.3/etc/hadoop/

hadoop103hadoop104上查看分发情况

cat /opt/module/hadoop-3.1.3/etc/hadoop/core-site.xml

1.4 单点 启动/停止 集群

  1. 启动HDFS集群/停止HDFS集群

    启动

    • 注意: 首次启动HDFS需要对NameNode进行格式化操作,在hadoop102执行:
    hdfs namenode -format
    
    • hadoop102启动namenode
     hdfs --daemon start namenode
    

    可以用jps检查namenode是否启动

    • hadoop102 hadoop103 hadoop104 分别启动 datanode
     hdfs --daemon start datanode
    
    • hadoop104 启动secondarynamenode
    hdfs --daemon start secondarynamenode
    

    停止

    • hadoop102停止namenode

      hdfs --daemon stop namenode
      
    • hadoop102 hadoop103 hadoop104 分别停止 datanode

      hdfs --daemon stop datanode
      
    • hadoop104 停止secondarynamenode

    hdfs --daemon stop secondarynamenode
    
  2. 启动YARN集群/停止YARN集群

    启动

    • hadoop103启动resourcemanager
    yarn --daemon start resourcemanager
    
    • hadoop102 hadoop103 hadoop104 分别启动 nodemanager
    yarn --daemon start nodemanager
    

    停止

    • hadoop103停止resourcemanager

      yarn --daemon stop resourcemanager
      
    • hadoop102 hadoop103 hadoop104 分别停止 nodemanager

      yarn --daemon stop nodemanager
      

格式 HDFS集群的 NameNode的注意事项

  • 集群只有首次搭建后需要对NameNode进行格式化操作
  • 如果集群在后期使用过程需要重新格式化,一定切记删除所有机器hadoop安装目录下的 data ,logs目录。

1.5 群启/群停 集群的操作

1.5.1 ssh 免密登录

实现多服务器之间的 ssh 免密登录,可在先了解ssh原理,
实现免密访问 hadoop102 hadoop103 hadoop104

  • 1、生成公钥和私钥:

    ssh-keygen -t rsa  # 敲4次回车
    

    生成的数据保存在/home/xu1an/.ssh

  • 2、将公钥拷贝到要免密登录的目标机器上:

    ssh-copy-id hadoop102
    ssh-copy-id hadoop103
    ssh-copy-id hadoop104
    

    在hadoop102,hadoop103,hadoop104上都要重复上面操作。

  • .ssh文件夹下(~/.ssh)的文件功能解释

known_hosts记录ssh访问过计算机的公钥(public key)
id_rsa生成的私钥
id_rsa.pub生成的公钥
authorized_keys存放授权过的无密登录服务器公钥
1.5.2 群起集群

1)配置workers

当执行群启/群停脚本的时候,首先会解析etc/hadoop/workers ,解析到的内容都是每一台机器的地址,脚本会自动执行在每一台机器上启动 dn nm 。

vim /opt/module/hadoop-3.1.3/etc/hadoop/workers

在该文件中增加如下内容:

hadoop102
hadoop103
hadoop104

**注意:**该文件中添加的内容结尾不允许有空格,文件中不允许有空行。

同步所有节点配置文件

my_rsync.sh /opt/module/hadoop-3.1.3/etc
  1. 启动/停止集群

注意:如果集群是第一次启动,需要在hadoop102节点格式化NameNode(注意格式化NameNode,会产生新的集群id,导致NameNode和DataNode的集群id不一致,集群找不到已往数据。如果集群在运行过程中报错,需要重新格式化NameNode的话,一定要先停止namenode和datanode进程,并且要删除所有机器的data和logs目录,然后再进行格式化。)

hdfs namenode -format
  • (hadoop102)启动/停止HDFS

    start-dfs.sh
    stop-dfs.sh
    
  • 在配置了ResourceManager的节点(hadoop103)启动/停止YARN

    start-yarn.sh
    stop-yarn.sh
    
  • Web端查看HDFS的NameNode

    浏览器中输入:http://hadoop102:9870

  • Web端查看YARN的ResourceManager

    浏览器中输入:http://hadoop103:8088

1.5.3 自定义集群的脚本

/home/xu1an/bin下创建群启/群停脚本my_cluster.sh

touch my_cluster.sh
chmod 744 my_cluster.sh

脚本内容如下:

#!/bin/bash

#参数校验
if [ $# -lt 1]
then
 echo '参数不能为空!!!'
 exit
fi

case $1 in
"start")
 #启动HDFS集群
 echo "===============启动HDFS集群===================="
 ssh hadoop102 /opt/module/hadoop-3.1.3/sbin/start-dfs.sh
 #启动YARN集群
 echo "===============启动YARN集群===================="
 ssh hadoop103 /opt/module/hadoop-3.1.3/sbin/start-yarn.sh
;;
 
"stop")
 #停止HDFS集群
 echo "===============停止HDFS集群===================="
 ssh hadoop102 /opt/module/hadoop-3.1.3/sbin/stop-dfs.sh
 #停止YARN集群
 echo "===============停止YARN集群===================="
 ssh hadoop103 /opt/module/hadoop-3.1.3/sbin/stop-yarn.sh
;;
 
*)
 echo '参数有误!!!'
 exit
;;
esac 
1.5.4 集群基本测试

官方的wordcount案例在集群上跑一遍。运行官方wordcount案例

http://hadoop102:9870/上创建wcinput文件并上传hello.txt。在hadoop102中进行操作:

hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input /output

同时,在http://hadoop103:8088/上可以观察到作业执行情况

  • 本地模式中:

     hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount file:///input file:///output
    

    /wcinput会被默认匹配为file:///wcinput

  • 完全分布式中:

    hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount hdfs://hadoop102:9820/input hdfs://hadoop102:9820/output
    

    而由于我们在core.xml中添加了配置hdfs://hadoop102:9820,那么/wcinput就会被匹配为hdfs://hadoop102:9820/wcinput

思考:当MR程序在集群运行的时候 / 代表什么意思?

答案:代表的是HDFS的根目录,有core-site.xml中的配置信息决定的

<!-- 指定NameNode的地址 -->
<property>
	<name>fs.defaultFS</name>
	<value>hdfs://hadoop102:9820</value>
</property>
1.5.5 配置历史服务器

历史服务器是针对MR程序执行的历史记录。

为了查看程序的历史运行情况,需要配置一下历史服务器。具体配置步骤如下:

  1. 配置mapred-site.xml

    /opt/module/hadoop-3.1.3/etc/hadoop下对mapred-site.xml文件进行修改

    该文件新增配置如下:

    <!-- 历史服务器端地址 -->
    <property>
        <name>mapreduce.jobhistory.address</name>
        <value>hadoop102:10020</value>
    </property>
    
    <!-- 历史服务器web端地址 -->
    <property>
        <name>mapreduce.jobhistory.webapp.address</name>
        <value>hadoop102:19888</value>
    </property>
    

    在hadoop102中单点启动,并测试

    mapred --daemon start historyserver
    
  2. 分发配置

    切记将配置mapred-site.xml,分发给其他机器。

    my_rsync /opt/module/hadoop-3.1.3/etc/hadoop/
    
1.5.6 配置日志的聚集

日志聚集概念:应用运行完成以后,将程序运行日志信息上传到HDFS系统上。日志是针对 MR 程序运行是所产生的的日志。

日志聚集功能好处:可以方便的查看到程序运行详情,方便开发调试。

**注意:**开启日志聚集功能,需要重新启动NodeManagerResourceManagerHistoryServer

开启日志聚集功能具体步骤如下:

  1. 配置yarn-site.xml

    vim yarn-site.xml
    

    在该文件里面增加如下配置。

    <!-- 开启日志聚集功能 -->
    <property>
        <name>yarn.log-aggregation-enable</name>
        <value>true</value>
    </property>
    <!-- 设置日志聚集服务器地址 -->
    <property>  
        <name>yarn.log.server.url</name>  
        <value>http://hadoop102:19888/jobhistory/logs</value>
    </property>
    <!-- 设置日志保留时间为7天 -->
    <property>
        <name>yarn.log-aggregation.retain-seconds</name>
        <value>604800</value>
    </property>
    
  2. 分发配置

    my_rsync $HADOOP_HOME/etc/hadoop/
    
  3. 关闭后启动NodeManager 、ResourceManage和HistoryServer

    my_cluster.sh stop
    mapred --daemon stop historyserver
    my_cluster.sh start
    mapred --daemon start historyserver
    
  4. 测试日志聚焦功能

    • 删除HDFS上已经存在的输出文件(输出文件不能重名)
    hadoop fs -rm -r /output
    
    • 执行WordCount程序
    hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input /output
    

    可通过历史服务器去查看日志

1.5.7 编写集群常用脚本
  1. 查看三台服务器java进程脚本:my_jps

    cd /home/xu1an/bin
    vim my_jps
    

    脚本内容如下:

    #!/bin/bash
    for host in hadoop102 hadoop103 hadoop104
    do
            echo =============== $host ===============
            ssh $host jps $@ | grep -v Jps
    done
    

    保存后退出,然后赋予脚本执行权限

    chmod 744 my_jps.sh 
    
  2. hadoop集群启停脚本(包含hdfs,yarn,historyserver):myhadoop.sh

    cd /home/xu1an/bin
    vim my_cluster
    

    脚本内容如下:

    #!/bin/bash
    
    #参数校验
    if [ $# -lt 1 ]
    then
     echo '参数不能为空!!!'
     exit
    fi
    
    case $1 in
    "start")
     #启动HDFS集群
     echo "===============启动HDFS集群===================="
     ssh hadoop102 /opt/module/hadoop-3.1.3/sbin/start-dfs.sh
     #启动YARN集群
     echo "===============启动YARN集群===================="
     ssh hadoop103 /opt/module/hadoop-3.1.3/sbin/start-yarn.sh
     #启动历史服务器(日志聚集)
     echo "=============启动历史服务器===================="
     ssh hadoop102 mapred --daemon start historyserver
     echo "Starting historyserver"
    ;;
    
    "stop")
     #停止历史服务器(日志聚集)
     echo "=============停止历史服务器===================="
     ssh hadoop102 mapred --daemon stop historyserver
     echo "Stopping historyserver"
     #停止HDFS集群
     echo "===============停止HDFS集群===================="
     ssh hadoop102 /opt/module/hadoop-3.1.3/sbin/stop-dfs.sh
     #停止YARN集群
     echo "===============停止YARN集群===================="
     ssh hadoop103 /opt/module/hadoop-3.1.3/sbin/stop-yarn.sh
    ;;
    
    *)
     echo '参数有误!!!'
     exit
    ;;
    esac 
    

    保存后退出,然后赋予脚本执行权限

    chmod 744 my_cluster
    

    分发/home/atguigu/bin目录,保证自定义脚本在三台机器上都可以使用

    my_rsync /home/xu1an/bin
    

1.6 总结

自此我们的分布式集群以及基本搭建完毕,也同时成功测试了hadoop的官方案例wordcount。后续我们将对hadoop内部的工作机制以及相关源码进行解析。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值