但行好事
莫论前程❤

hadoop集群安装手册

安装步骤

  1. 上传hadoop安装包. rz

  2. 解压文件到/data文件夹下

    root   $ mkdir /data
    hadoop $ sudo chown hadoop:hadoop /data               #  修改data文件夹拥有者和所属组
    hadoop $ sudo chmod 755 /data                        #  设置文件夹权限 4读 2写 1可执行
    hadoop $ tar -zxvf hadoop.tar.gz -C /data
    
  3. drwxr-xr-x 2 hadoop hadoop  4096 Dec 16 09:12 bin       ### 可执行脚本,常见的普通操作
    drwxr-xr-x 3 hadoop hadoop  4096 Dec 16 09:12 etc        ### 配置文件
    drwxr-xr-x 3 hadoop hadoop  4096 Feb  1 15:40 hdfs      
    drwxr-xr-x 2 hadoop hadoop  4096 Dec 16 09:12 include
    drwxr-xr-x 3 hadoop hadoop  4096 Dec 16 09:12 lib        ### 本地库文件
    drwxr-xr-x 2 hadoop hadoop  4096 Dec 16 09:12 libexec
    -rwxr-xr-x 1 hadoop hadoop 86424 Dec 16 09:12 LICENSE.txt
    drwxr-xr-x 2 hadoop hadoop  4096 Feb  1 17:23 logs     ### 日志
    -rwxr-xr-x 1 hadoop hadoop 14978 Dec 16 09:12 NOTICE.txt
    -rwxr-xr-x 1 hadoop hadoop  1366 Dec 16 09:12 README.txt
    drwxr-xr-x 2 hadoop hadoop  4096 Dec 16 09:12 sbin     ### 系统相关的一些执行脚本,有hadoop的启                                                           动和停止相关服务的执行脚本
    drwxr-xr-x 4 hadoop hadoop  4096 Dec 16 09:12 share    ###  大量的jar包  
    drwxr-xr-x 2 hadoop hadoop  4096 Jan 31 16:48 tmp
    

1. 修改配置文件

cd etc/hadoop

需要修改的有:

1.hadoop-env.sh.

(env—environment, hadoop也有一些环境变量的配置)

在该文件中修改java_home,该脚本有些问题,它是通过变量去获取的,但总是不容易获取到系统中

java_home,所以在这里直接写死

Hadoop启动的时候也要去读一些配置文件,读取

​ 2. core-site.xml,

​ 3. hdfs-site.xml

​ 4. mapred-site.xml。

​ template

  1. yarn-site.xml

里的配置文件。对应其四个组件:

hadoop核心:
    $ HDFS: Hadoop Distributed File System     # 分布式文件系统
    $ YARN: Yet Another Resource Negotiator    # 资源管理调度系统
    $ MapReduce:                             # 分布式运算框架

1. 修改hadoop-env.sh

$ vim hadoop-env.sh

#The java implementation to use
export JAVA_HOME=${JAVA_HOME}
------------->
export JAVA_HOME=/usr/local/java/jdk1.8_144         # 将环境变量写死

**查看环境变量 **

echo $JAVA_HOME 输出变量名的值

2. 修改core-site.xml

<!-- 指定hadoop所使用的(fileSystem)文件系统schema(url),hdfs中老大的地址 -->
<property>
    <name>fs.defaultFS</name>    
    <!-- 对比记忆于jdbc:mysql://localhost:3306    hdfs协议 -->
    <value>hdfs://主节点主机名:9000</value>   
</property>
<!-- 指定hadoop运行时产生文件的存储目录 -->
<property>
    <name>hadoop.tmp.dir</name>
    <!-- 存放hadoop运行时的文件  -->
    <value>/home/hadoop/hadoop-2.4.1/data</value> 
</property>

注:从分布式存储的角度来说,集群中的结点由一个NameNode和若干个DataNode组成,另有一个SecondaryNameNode作为NameNode的备份。从分布式应用的角度来说,集群中的结点由一个JobTracker和若干个TaskTracker组成,JobTracker负责任务的调度,TaskTracker负责并行执行任务。TaskTracker必须运行在DataNode上,这样便于数据的本地计算。JobTracker和NameNode则无须在同一台机器上。

2.2 core-site.xml生产环境_HA部署模式(集群)

<configuration>
    <property>
        <name>fs.trash.interval</name>
        <value>1440</value>
    </property>
    <!-- Hadoop HA部署方式下namenode访问地址,bigdatacluster-ha是名字可自定义,后面hdfs-site.xml会用到 -->
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://bigdatacluster-ha</value>
    </property>
    <!--hadoop访问文件的IO操作都需要通过代码库。因此,在很多情况下,io.file.buffer.size都被用来设置SequenceFile中用到的读/写缓存大小。不论是对硬盘或者是网络操作来讲,较大的缓存都可以提供更高的数据传输,但这也就意味着更大的内存消耗和延迟。这个参数要设置为系统页面大小的倍数,以byte为单位,默认值是4KB,一般情况下,可以设置为64KB(65536byte),这里设置128K-->
    <property>
        <name>io.file.buffer.size</name>
        <value>131072</value>
    </property>
    <!-- 指定hadoop临时目录 -->
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/data/hadoop/tmp</value>
    </property>
    <!-- 指定zookeeper地址 -->
    <property>
        <name>ha.zookeeper.quorum</name>
        <value>OP-APM-02:2181,OP-APM-03:2181,OP-APM-04:2181</value>
    </property>
    <property>
        <name>ha.zookeeper.session-timeout.ms</name>
        <value>300000</value>
    </property>
    <!-- 指定Hadoop压缩格式,Apache官网下载的安装包不支持snappy,需要自己编译安装,如何编译安装包我在博客http://aperise.iteye.com/blog/2254487有讲解,不适用snappy的话可>
以不配置 -->
    <property>
        <name>io.compression.codecs</name>
        <value>org.apache.hadoop.io.compress.SnappyCodec</value>
    </property>
</configuration>

3.修改 hdfs-site.xml

<!-- 与hdfs运行时的具体参数有关 -->
<property>
    <name>dfs.replication</name>    <!--副本数     伪分布式写1    切块大小默认128M -->
    <value>1</value>
</property>

3.3 hdfs-site.xml生产环境配置(集群)

<configuration>
<!--指定hdfs的nameservice为bigdatacluster-ha,需要和core-site.xml中的保持一致 -->
    <property>
        <name>dfs.nameservices</name>
        <value>bigdatacluster-ha</value>
    </property>
    <property>
        <name>dfs.datanode.du.reserved</name>
        <value>107374182400</value>
    </property>
    <!-- bigdatacluster-ha下面有两个NameNode,分别是namenode1,namenode2 -->
    <property>
        <name>dfs.ha.namenodes.bigdatacluster-ha</name>
        <value>namenode1,namenode2</value>
    </property>
    <!-- namenode1的RPC通信地址,这里端口要和core-site.xml中fs.defaultFS保持一致 -->
    <property>
        <name>dfs.namenode.rpc-address.bigdatacluster-ha.namenode1</name>
        <value>OP-APM-02:9000</value>
    </property>
    <!-- namenode1的http通信地址 -->
    <property>
        <name>dfs.namenode.http-address.bigdatacluster-ha.namenode1</name>
        <value>OP-APM-02:50070</value>
    </property>
    <!-- namenode2的RPC通信地址,这里端口要和core-site.xml中fs.defaultFS保持一致 -->
    <property>
        <name>dfs.namenode.rpc-address.bigdatacluster-ha.namenode2</name>
        <value>OP-APM-03:9000</value>
    </property>
    <!-- namenode2的http通信地址 -->
    <property>
        <name>dfs.namenode.http-address.bigdatacluster-ha.namenode2</name>
        <value>OP-APM-03:50070</value>
    </property>

    <!-- 指定NameNode的元数据在JournalNode上的存放位置 -->
    <property>
        <name>dfs.namenode.shared.edits.dir</name>
        <value>qjournal://OP-APM-05:8485;OP-APM-06:8485;OP-APM-07:8485;/bigdatacluster-ha</value>
    </property>

    <!-- 配置失败自动切换实现方式 -->
    <property>
        <name>dfs.client.failover.proxy.provider.bigdatacluster-ha</name>
        <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
    </property>

    <!-- 配置隔离机制,主要用户远程管理监听其他机器相关服务 -->
    <property>
        <name>dfs.ha.fencing.methods</name>
        <value>sshfence</value>
    </property>
    <!-- 使用隔离机制时需要ssh免密码登陆 -->
    <property>
        <name>dfs.ha.fencing.ssh.private-key-files</name>
        <value>/home/hadoop/.ssh/id_rsa</value>
    </property>

    <!-- 指定NameNode的元数据在JournalNode上的存放位置 -->
    <property>
        <name>dfs.journalnode.edits.dir</name>
        <value>/data/hadoop/journal</value>
    </property>

    <!--指定支持高可用自动切换机制-->
    <property>
        <name>dfs.ha.automatic-failover.enabled</name>
        <value>true</value>
    </property>

    <!--指定namenode名称空间的存储地址-->
    <property>
        <name>dfs.namenode.name.dir</name>
        <value>/data/hadoop/hdfs/name</value>
    </property>

    <!--指定datanode数据存储地址-->
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>/data/hadoop/hdfs/data</value>
    </property>

    <!--指定数据冗余份数-->
    <property>
        <name>dfs.replication</name>
        <value>3</value>
    </property>

    <!--指定可以通过web访问hdfs目录-->
    <property>
        <name>dfs.webhdfs.enabled</name>
        <value>true</value>
    </property>

    <property>
        <name>ha.zookeeper.quorum</name>
        <value>OP-APM-02:2181,OP-APM-03:2181,OP-APM-04:2181</value>
    </property>


    <property>
        <name>dfs.namenode.handler.count</name>
        <value>600</value>
        <description>The number of server threads for the namenode.</description>
    </property>
    <property>
        <name>dfs.datanode.handler.count</name>
        <value>600</value>
        <description>The number of server threads for the datanode.</description>
    </property>
    <property>
        <name>dfs.client.socket-timeout</name>
        <value>600000</value>
    </property>
    <property>
        <!--这里设置Hadoop允许打开最大文件数,默认4096,不设置的话会提示xcievers exceeded错误-->
        <name>dfs.datanode.max.transfer.threads</name>
        <value>409600</value>
    </property>
</configuration>

4. 修改mapred-site.xml

如果名字为mapred-site.xml.tempalte 则需要修改其名字为mapred-site.xml,否则hadoop不读取

<property>
    <name>mapreduce.framework.name</name>
<!-- 将mapreduce这个运算程序放在yarn资源管理调度系统上去跑,不指定的话,mapreduce程序会在本地上跑 -->
    <value>yarn</value>    
</property>                 
<!-- yarn也是一个集群 -->

4.4 mapred-site.xml生产环境配置(集群)

<configuration>
    <!-- 配置MapReduce运行于yarn中 -->
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
    <property>
        <name>mapreduce.job.maps</name>
        <value>12</value>
    </property>
    <property>
        <name>mapreduce.job.reduces</name>
        <value>12</value>
    </property>

    <!-- 指定Hadoop压缩格式,Apache官网下载的安装包不支持snappy,需要自己编译安装,如何编译安装包见http://aperise.iteye.com/blog/2254487,不适用snappy的话可以不配置 -->
    <property>
        <name>mapreduce.output.fileoutputformat.compress</name>
        <value>true</value>
        <description>
            Should the job outputs be compressed?
        </description>
    </property>
    <property>
        <name>mapreduce.output.fileoutputformat.compress.type</name>
        <value>RECORD</value>
        <description>If the job outputs are to compressed as SequenceFiles, how should
               they be compressed? Should be one of NONE, RECORD or BLOCK.
        </description>
    </property>
    <property>
        <name>mapreduce.output.fileoutputformat.compress.codec</name>
        <value>org.apache.hadoop.io.compress.SnappyCodec</value>
        <description>If the job outputs are compressed, how should they be compressed?
        </description>
    </property>
    <property>
        <name>mapreduce.map.output.compress</name>
        <value>true</value>
        <description>Should the outputs of the maps be compressed before being
               sent across the network. Uses SequenceFile compression.
        </description>
    </property>
    <property>
        <name>mapreduce.map.output.compress.codec</name>
        <value>org.apache.hadoop.io.compress.SnappyCodec</value>
        <description>If the map outputs are compressed, how should they be
               compressed?
        </description>
    </property>
</configuration>

5. 修改yarn-site.xml

<property>
    <name>yarn.resourcemanager.hostname</name>
    <value>本台主机名</value>   <!-- 配置yarn集群中的老大,伪分布式这里写本机名 -->
</property>
<property>
    <name>yarn.nodemanager.aux-services</name>
    <!-- 制定mapred产生的中间结果怎么传递给reducer的,即reducer获取数据的方式 -->
    <value>mapreduce_shuffle</value>   
</property>                             

因为hadoop在运行的时候需要监听一些端口,而这些端口默认都被linux的防火墙给挡住了,所以需要先关闭防火墙

5.5 yarn-site.xml生产环境配置(集群)

<configuration>
    <property>
        <name>yarn.log-aggregation-enable</name>
        <value>true</value>
    </property>
    <!--在HDFS上聚合的日志最长保留多少秒。3天-->
    <property>
        <name>yarn.log-aggregation.retain-seconds</name>
        <value>259200</value>
    </property>

    <!--resourcemanager失联后重新链接的时间-->
    <property>
        <name>yarn.resourcemanager.connect.retry-interval.ms</name>
        <value>2000</value>
    </property>

    <property>
        <name>yarn.resourcemanager.zk-address</name>
        <value>OP-APM-01:2181,OP-APM-02:2181,OP-APM-03:2181,OP-APM-04:2181</value>
    </property>
    <property>
        <name>yarn.resourcemanager.cluster-id</name>
        <value>besttonecluster-yarn</value>
    </property>
    <!--开启resourcemanager HA,默认为false-->
    <property>
        <name>yarn.resourcemanager.ha.enabled</name>
        <value>true</value>
    </property>
    <property>
        <name>yarn.resourcemanager.ha.rm-ids</name>
        <value>rm1,rm2</value>
    </property>
    <property>
        <name>yarn.resourcemanager.hostname.rm1</name>
        <value>OP-APM-02</value>
    </property>
    <property>
        <name>yarn.resourcemanager.hostname.rm2</name>
        <value>OP-APM-03</value>
    </property>
    <!--配置rm1-->
     <property>
        <name>yarn.resourcemanager.webapp.address.rm1</name>
        <value>OP-APM-02:8088</value>
    </property>
    <!--配置rm2-->
    <property>
        <name>yarn.resourcemanager.webapp.address.rm2</name>
        <value>OP-APM-03:8088</value>
    </property>
    <!--开启故障自动切换-->
    <property>
        <name>yarn.resourcemanager.ha.automatic-failover.enabled</name>
        <value>true</value>
    </property>
    <property>
        <name>yarn.resourcemanager.ha.automatic-failover.embedded</name>
        <value>true</value>
    </property>
    <property>
        <name>yarn.resourcemanager.ha.automatic-failover.zk-base-path</name>
        <value>/yarn-leader-election</value>
    </property>

    <!--开启自动恢复功能-->
    <property>
        <name>yarn.resourcemanager.recovery.enabled</name>
        <value>true</value>
    </property>
    <property>
        <name>yarn.resourcemanager.store.class</name>
        <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
    </property>

    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>
    <property>
        <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
        <value>org.apache.hadoop.mapred.ShuffleHandler</value>
    </property>
</configuration>

6. 修改slaves

$ vim slaves
# 指定datanode所在服务器
OP-APM-07
OP-APM-08
OP-APM-09
OP-APM-10
OP-APM-11
===========
# 伪分布式写
localhost

2. 第一次启动hadoop之前需要初始化

因为hdfs组件是一个文件系统,需要格式化一下

步骤

  1. 到hadoop的bin目录下,如果不配置环境变量则命令前加./

    配置环境变量

    $ sudo vim /etc/profile
    export HAOOP_HOME = /data/hadoop/
    export PATH= $HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PTAH
    $ source /etc/profile  使profile立即生效
    
  2. 执行格式化命令:

$ hadoop namenode -format
# 格式化成功
15/01/09 22:49:50 INFO common.Storage:Storage directory /data/hadoop//hadoop-2.4/data/dfs/name has been successfully formatted. 
  1. 格式化之后它在data目录下新建了一个dfs子文件夹,并在dfs下创建了一个name文件夹(由namenode来进行读写),并在其下面创建了一个current文件夹.
./data/
./data/dfs/
./data/dfs/name/
./data/dfs/name/current
-rw-r----- 1 hadoop hadoop  173850 Feb  3 01:23 fsimage_0000000000000008727
-rw-r----- 1 hadoop hadoop      62 Feb  3 01:23 fsimage_0000000000000008727.md5
-rw-r----- 1 hadoop hadoop       5 Feb  3 02:14 seen_txid
-rwxr-xr-x 1 hadoop hadoop     207 Feb  1 15:40 VERSION
# Md5是校验码
# Namenode就是管理源数据的。

3. 启动hadoop

  • 进入sbin目录

    cd /data/hadoop/sbin/

    -rwxr-xr-x 1 hadoop hadoop 6452 Dec 16 09:12 hadoop-daemon.sh
    -rwxr-xr-x 1 hadoop hadoop 1360 Dec 16 09:12 hadoop-daemons.sh
    -rwxr-xr-x 1 hadoop hadoop 1640 Dec 16 09:12 hdfs-config.cmd
    -rwxr-xr-x 1 hadoop hadoop 1427 Dec 16 09:12 hdfs-config.sh
    -rwxr-xr-x 1 hadoop hadoop 1648 Dec 16 09:12 refresh-namenodes.sh
    -rwxr-xr-x 1 hadoop hadoop 1779 Dec 16 09:12 start-all.cmd
    -rwxr-xr-x 1 hadoop hadoop 1471 Dec 16 09:12 start-all.sh
    -rwxr-xr-x 1 hadoop hadoop 1401 Dec 16 09:12 start-dfs.cmd
    -rwxr-xr-x 1 hadoop hadoop 3734 Dec 16 09:12 start-dfs.sh
    -rwxr-xr-x 1 hadoop hadoop 1571 Dec 16 09:12 start-yarn.cmd
    -rwxr-xr-x 1 hadoop hadoop 1347 Dec 16 09:12 start-yarn.sh
    -rwxr-xr-x 1 hadoop hadoop 1770 Dec 16 09:12 stop-all.cmd
    -rwxr-xr-x 1 hadoop hadoop 1462 Dec 16 09:12 stop-all.sh
    -rwxr-xr-x 1 hadoop hadoop 1455 Dec 16 09:12 stop-dfs.cmd
    -rwxr-xr-x 1 hadoop hadoop 3206 Dec 16 09:12 stop-dfs.sh
    -rwxr-xr-x 1 hadoop hadoop 1642 Dec 16 09:12 stop-yarn.cmd
    -rwxr-xr-x 1 hadoop hadoop 1340 Dec 16 09:12 stop-yarn.sh
    -rwxr-xr-x 1 hadoop hadoop 4295 Dec 16 09:12 yarn-daemon.sh
    -rwxr-xr-x 1 hadoop hadoop 1353 Dec 16 09:12 yarn-daemons.sh
    
  • start-dfs.sh      # 启动hdfs文件管理系统
    # 它会先启动namenode,然后登陆到其他服务器上去启动datanode,之后secondarynamenode.
    

    检验

$ jps                   # 查看进程
datanode 
SecondaryNode
NameNode

启动start-yarn.sh

启动yarn daemons          # 资源管理调度系统  守护进程
启动 resourcemanager      # 资源管理器   老大
启动 nodemanager          # 节点管理器

Hadoop集群启动的时候只需要在一台机器上启动就好啦,不需要到每台机器上去启动。

在一台机器上启动start-hdfs.shstart-yarn.sh就好啦,但有个问题就是每次启动的时候都需要输入密码很麻烦。

所以需要设置免密钥登录 .详细操作见: ssh免秘钥登录

4. 测试安装是否成功

测试mapreduce,hdfs和yarn两个集群能否使用

  • 测试hdfs

​ 1 打开不能直接用主机名去访问,http://slave:50070 slave主机名

​ 注意:不是https:

​ 因为windows系统里面不认识这个主机名,

需要在windows系统里的hosts里改一下配置文件

C://system32/drivers/etc/hosts文件下,加入一个:

192.168.19.100  主机名(比如slave)

能查看到namenode

状态 active

hdfs端口:9090

summary摘要信息

查看hdfs的文件系统:

Utilities--> Browse the file system
# 可以查看linux系统中hdfs中的文件,可以下载

测试mapreduce

$ cd /data/hadoop/share/hadoop/mapreduce
# 计算圆周率 参数 maps的任务数量  map的取样数  //取样数越高 精确度越高
$ hadoop jar hadoop-mapreduce-examples-2.4.1.jar pi 2 2

5. hdfs操作命令

上传文件到hdfs集群中

$ hadoop fs -put jdk-1.7.tar.gz  hdfs://op-apm-02:9000/
或
$ hadoop fs -put jdk-1.7.tar.gz  /hbase

此时该文件被切分成N份放在data目录下的name文件夹下,

当linux系统中的文件删除掉之后,可以从抽象的hdfs文件系统中下载下来.

hdfs文件系统与本地的文件之间没有关系.

上传到hdfs文件系统的东西,是datanode文件的切块,被放到datanode所在的文件系统里面,即dfs文件夹下的data或name中.

下载hdfs中的文件:

$ hadoop fs -get hdfs://op-apm-02:9000/jdk-linux-1.7.tar.gz 
或
$ hadoop fs -get /hbase

查看hdfs中的文件:

$ hadoop fs -ls /user/hadoop/output   # 查看指定目录下的文件和文件夹。
                                   # /user/hadoop/output是HDFS上的目录,不是本地目录
$ hadoop fs -cat  /user/hadoop/output # 查看文件内容

Hadoop fs 访问hdfs的指令,表示操作文件系统 fs(filesystem)

常用参数:
$ hadoop fs  参数 
###################################
-ls                 ### 显示
-cat                ### 查看文件内容
-put                ### 存放数据
-get                ### 获取数据 
###################################

什么都不打只写hadoop fs  会显示所有的参数
-appendToFile        ### 追加数据 hdfs不支持修改但可以追加内容
-chgrp              ### 修改文件所属的组
-chmod              ### 修改权限

ps:

### -chmod 修改权限
$ hadoop fs -chmod 777 /jdk-1.7.tar.gz
### -chown 修改所属组  
$ hadoop fs -chown angelababy:mygirls /jdk-1.7-linux.tar.gz
# 其中angelababy是拥有者 mygrils是所属组

hadoop学习笔记

hadoop集群解决的问题:

  • 海量数据的存储(HDFS)
  • 海量数据的分析(MapReduce)
  • 资源管理调度(YARN)

hadoop是好多框架组成的生态系统

HDFS用来存储海量的数据

HDFS的架构

  • 主从结构:
    • 主节点: namenode
    • 从节点: 有很多个 datanode

    namenode负责

    • 接收用户操作请求
    • 维护文件系统的目录结构
    • 管理文件与block之间关系,block与datanode之间关系

    datanode负责

    • 存储文件
    • 文件被分成块(block)存储在磁盘上
    • 为保证数据安全,文件会有多个副本

![图片1](C:\Users\liupenggc.FEINNO\Pictures\Camera Roll\图片1.png)

metadata: 元数据 client:客户,委托人 replication复制.回答 ops:并行服务器 rack:机架

hdfs(工作)实现思想:

  1. hdfs是通过分布式集群来存储文件的,为客户提供了一个便捷的访问方式,就是一个虚拟的目录结构
  2. 文件存储到hdfs集群中的时候是被切分成block的
  3. 文件的block’存放在若干台datanode节点上
  4. hdfs文件系统中的文件与真实的block之间有映射关系,由namenode管理
  5. 每一个block在集群中会存储多个副本,好处是可以提高数据的可靠性,还可以提高访问的吞吐量.
赞(1) 打赏
未经允许不得转载:刘鹏博客 » hadoop集群安装手册
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏