1、集群规划
1.1、集群资源规划
1.2、HostName
cat > /etc/hosts << EOF
192.168.xxx.xxx xxx-245
192.168.xxx.xxx xxx-246
192.168.xxx.xxx xxx-247
192.168.xxx.xxx xxx-248
EOF
基于 Rocky Linux 9.4 操作系统,详细演示了 Hadoop 3.4.2 高可用集群的搭建过程。内容涉及集群规划、主机名解析、用户免密登录、JDK 环境变量配置、Zookeeper 集群部署、HDFS 与 YARN 高可用配置(包括 JournalNode、NameNode、ResourceManager、ZKFC 等组件)。提供了完整的配置文件示例(core-site.xml, hdfs-site.xml, yarn-site.xml 等)及启动验证命令,适用于大数据平台运维参考。
cat > /etc/hosts << EOF
192.168.xxx.xxx xxx-245
192.168.xxx.xxx xxx-246
192.168.xxx.xxx xxx-247
192.168.xxx.xxx xxx-248
EOF
ansible cluster -m user -a "name=hadoop password={{'Hadoop.2026'|password_hash('sha512')}}"
anisble cluster -m shell -a "echo 'hadoop ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers"
sudo -u hadoop -i ssh-keygen -t rsa -b 2048 -P '' -f ~/.ssh/id_rsa
ssh-copy-id 192.168.xxx.xxx
ssh-copy-id 192.168.xxx.xxx
ssh-copy-id 192.168.xxx.xxx
ssh-copy-id 192.168.xxx.xxx
vi /etc/profile
# jdk
export JAVA_HOME=/usr/java/jdk-17
export PATH=$JAVA_HOME/bin:$PATH
source /etc/profile
# 查看核心数
cat /proc/cpuinfo | grep "model name" && cat /proc/cpuinfo | grep "physical id"
# 查看内存大小
cat /proc/meminfo | grep MemTotal
# 查看磁盘
disk -l | grep Disk
uname -a
# 查看内核/操作系统/CPU 信息的 linux 系统信息命令
head -n 1 /etc/issue
# 查看操作系统版本,是数字 1 不是字母 L
cat /proc/cpuinfo
# 查看 CPU 信息的 linux 系统信息命令
hostname
# 查看计算机名的 linux 系统信息命令
lspci -tv
# 列出所有 PCI 设备
lsusb -tv
# 列出所有 USB 设备的 linux 系统信息命令
lsmod
# 列出加载的内核模块
env
# 查看环境变量资源
free -m
# 查看内存使用量和交换区使用量
df -h
# 查看各分区使用情况
du -sh
# 查看指定目录的大小
grep MemTotal /proc/meminfo
# 查看内存总量
grep MemFree /proc/meminfo
# 查看空闲内存量
uptime
# 查看系统运行时间、用户数、负载
cat /proc/loadavg
# 查看系统负载
disk and partition
mount | column -t
# 查看挂接的分区状态
fdisk -l
# 查看所有分区
swapon -s
# 查看所有交换分区
hdparm -i /dev/hda
# 查看磁盘参数 (仅适用于 IDE 设备)
dmesg | grep IDE
# 查看启动时 IDE 设备检测状况
network
ifconfig
# 查看所有网络接口的属性
iptables -L
# 查看防火墙设置
route -n
# 查看路由表
netstat -lntp
# 查看所有监听端口
netstat -antp
# 查看所有已经建立的连接
netstat -s
# 查看网络统计信息
process
ps -ef
# 查看所有进程
top
# 实时显示进程状态
user
w
# 查看活动用户
id
# 查看指定用户信息
last
# 查看用户登录日志
cut -d: -f1 /etc/passwd
# 查看系统所有用户
cut -d: -f1 /etc/group
# 查看系统所有组
crontab -l
# 查看当前用户的计划任务
service
chkconfig --list
# 列出所有系统服务
chkconfig --list | grep on
# 列出所有启动的系统服务程序
rpm -qa
# 查看所有安装的软件包
cat /proc/cpuinfo
# 查看 CPU 相关参数的 linux 系统命令
cat /proc/partitions
# 查看 linux 硬盘和分区信息的系统信息命令
cat /proc/meminfo
# 查看 linux 系统内存信息的 linux 系统命令
cat /proc/version
# 查看版本,类似 uname -r
cat /proc/ioports
# 查看设备 io 端口
cat /proc/interrupts
# 查看中断
cat /proc/pci
# 查看 pci 设备的信息
cat /proc/swaps
# 查看所有 swap 分区的信息
# 分发
ansible cluster -m copy -a 'src=/opt/software/apache-zookeeper-3.9.4-bin.tar.gz dest=/opt/software/'
# 解压
ansible cluster -m shell -a "tar -xvf /opt/software/apache-zookeeper-3.9.4-bin.tar.gz -C /opt/apps"
# 改名
ansible cluster -m shell -a "mv /opt/apps/apache-zookeeper-3.9.4-bin /opt/apps/zookeeper-3.9.4"
# 基本时间单位(毫秒)
tickTime=2000
# Leader 选举初始化超时时间
initLimit=10
# 与 Leader 同步的超时时间
syncLimit=5
# 客户端连接端口
clientPort=2181
# 数据存储目录
dataDir=/data/zookeeper/data
# 集群节点配置(格式:server.ID=主机名:选举端口:通信端口)
server.1=xxx-246:2888:3888
server.2=xxx-247:2888:3888
server.3=xxx-248:2888:3888
# 自动清理频率(小时)
autopurge.purgeInterval=24
# 保留快照数量
autopurge.snapRetainCount=3
注:每个节点都要按配置文件修改
ansible cluster -m shell -a "mkdir -p /data/zookeeper/data/"
anisble cluster -m shell -a "echo '1' > /data/zookeeper/data/myid"
# zookeeper
export ZK_HOME=/opt/apps/zookeeper-3.9.4
export PATH=$PATH:$ZK_HOME/bin
source /etc/profile
ansible cluster -m copy -a 'src=/opt/apps/zookeeper-3.9.4/conf/zoo.cfg dest=/opt/apps/zookeeper-3.9.4/conf/'
vi bin/zkEnv.sh
# 修改
ZOO_LOG_DIR=/data/zookeeper/log
# 分发
ansible cluster -m copy -a 'src=/opt/apps/zookeeper-3.9.4/bin/zkEnv.sh dest=/opt/apps/zookeeper-3.9.4/bin'
ansible cluster -m shell -a "mkdir -p /data/zookeeper/{data,log}"
anisble cluster -m shell -a "chown -R hadoop:hadoop /opt/apps/zookeeper-3.9.4"
anisble cluster -m shell -a "chown -R hadoop:hadoop /data/zookeeper/"
zkServer.sh start
zkServer.sh status
ansible cluster -m shell -a '/opt/apps/zookeeper-3.9.4/bin/zkServer.sh restart'
anisble cluster -m shell -a '/opt/apps/zookeeper-3.9.4/bin/zkServer.sh status'
# 解压
tar -xzf hadoop-3.4.2.tar.gz -C /opt/apps/
anisble cluster -m shell -a "tar -xzf /opt/software/hadoop-3.4.2.tar.gz -C /opt/apps"
export JAVA_HOME=/usr/java/jdk-17
export HADOOP_OPTS="--add-opens java.base/java.lang=ALL-UNNAMED"
export HADOOP_LOG_DIR=/data/hadoop/log
export HADOOP_CLASSPATH=$HADOOP_HOME/lib/*:$HADOOP_HOME/etc/hadoop/*
export HADOOP_CONF_DIR=/opt/apps/hadoop-3.4.2/etc/hadoop
export JAVA_HOME=/usr/java/jdk-17
xxx-246
xxx-247
xxx-248
<property>
<name>yarn.scheduler.capacity.maximum-am-resource-percent</name>
<value>0.5</value>
</property>
<property>
<name>yarn.scheduler.capacity.resource-calculator</name>
<value>org.apache.hadoop.yarn.util.resource.DominantResourceCalculator</value>
</property>
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- 集群名称 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hdfs-ha</value>
</property>
<!-- 指定 hadoop 运行时产生文件的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/data/hadoop/data/tmp</value>
</property>
<!-- 指定要连接的 zkServer 地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>xxx-246:2181,xxx-247:2181,xxx-248:2181</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.groups</name>
<value>*</value>
</property>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- namenode 存储目录 -->
<property>
<name>dfs.namenode.name.dir</name>
<value>/data/hadoop/data/namenode</value>
</property>
<!-- datanode 数据存储目录 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>/data/hadoop/data/datanode</value>
</property>
<!-- journalnode 数据存储目录 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/data/hadoop/data/journal</value>
</property>
<!-- 完全分布式集群名称 -->
<property>
<name>dfs.nameservices</name>
<value>hdfs-ha</value>
</property>
<!-- 集群中的 namenode 节点都有哪些 -->
<property>
<name>dfs.ha.namenodes.hdfs-ha</name>
<value>nn-246,nn-247,nn-248</value>
</property>
<!-- namenode 的 RPC 通信地址 -->
<property>
<name>dfs.namenode.rpc-address.hdfs-ha.nn-246</name>
<value>xxx-246:9000</value>
</property>
<property>
<name>dfs.namenode.rpc-address.hdfs-ha.nn-247</name>
<value>xxx-247:9000</value>
</property>
<property>
<name>dfs.namenode.rpc-address.hdfs-ha.nn-248</name>
<value>xxx-248:9000</value>
</property>
<!-- namenode 的 http 通信地址 -->
<property>
<name>dfs.namenode.http-address.hdfs-ha.nn-246</name>
<value>xxx-246:9870</value>
</property>
<property>
<name>dfs.namenode.http-address.hdfs-ha.nn-247</name>
<value>xxx-247:9870</value>
</property>
<property>
<name>dfs.namenode.http-address.hdfs-ha.nn-248</name>
<value>xxx-248:9870</value>
</property>
<!-- 指定 namenode 元数据在 journalnode 上的存放位置,journalnode 用于同步主备 namenode 之间的 edits 文件 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://xxx-246:8485;xxx-247:8485;xxx-248:8485/hdfs-ha</value>
</property>
<!-- 访问代理类:client 用于确定哪个 NameNode 为 Active -->
<property>
<name>dfs.client.failover.proxy.provider.hdfs-ha</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>
<!-- 使用隔离机制时需要 ssh 秘钥登陆 -->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop/.ssh/id_rsa</value>
</property>
<!-- 启用 namenode 故障自动转移 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- 设置数据块应该被复制的份数,也就是副本数,默认:3 -->
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
</configuration>
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- 指定 MapReduce 框架使用的资源管理器名称,这里设置为 YARN -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!-- 每个 Map Task 需要的内存量 -->
<property>
<name>mapreduce.map.memory.mb</name>
<value>2048</value>
</property>
<!-- Map 任务 JVM 堆内存上限(通常为内存分配的 80%,避免 OOM) -->
<property>
<name>mapreduce.map.java.opts</name>
<value>-Xmx1638m</value>
</property>
<!-- 每个 Reduce Task 需要的内存量 -->
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>4096</value>
</property>
<!-- Reduce 任务 JVM 堆内存上限(建议不超过内存分配的 85%) -->
<property>
<name>mapreduce.reduce.java.opts</name>
<value>-Xmx3276m</value>
</property>
<!-- 任务内部排序缓冲区大小 -->
<property>
<name>mapreduce.task.io.sort.mb</name>
<value>128</value>
</property>
<property>
<name>yarn.app.mapreduce.am.env</name>
<value>HADOOP_MAPRED_HOME=/opt/apps/hadoop-3.4.2</value>
</property>
<property>
<name>mapreduce.map.env</name>
<value>HADOOP_MAPRED_HOME=/opt/apps/hadoop-3.4.2</value>
</property>
<property>
<name>mapreduce.reduce.env</name>
<value>HADOOP_MAPRED_HOME=/opt/apps/hadoop-3.4.2</value>
</property>
<!-- 历史服务器端地址 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>xxx-248:10020</value>
</property>
<!-- 历史服务器 web 端地址 -->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>xxx-248:19888</value>
</property>
</configuration>
<?xml version="1.0"?>
<configuration>
<!-- nodemanager 获取数据的方式 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!-- 启用 resourcemanager ha -->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!-- 声明 resourcemanager 的地址 -->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>yarn-ha</value>
</property>
<!-- 指定 resourcemanager 的逻辑列表 -->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm-246,rm-247,rm-248</value>
</property>
<!-- rm-246 的配置 -->
<!-- 指定 rm-246 的主机名 -->
<property>
<name>yarn.resourcemanager.hostname.rm-246</name>
<value>xxx-246</value>
</property>
<!-- 指定 rm-246 的 web 端地址 -->
<property>
<name>yarn.resourcemanager.webapp.address.rm-246</name>
<value>xxx-246:9088</value>
</property>
<!-- rm-247 的配置 -->
<!-- 指定 rm-247 的主机名 -->
<property>
<name>yarn.resourcemanager.hostname.rm-247</name>
<value>xxx-247</value>
</property>
<!-- 指定 rm-247 的 web 端地址 -->
<property>
<name>yarn.resourcemanager.webapp.address.rm-247</name>
<value>xxx-247:9088</value>
</property>
<!-- rm-248 的配置 -->
<!-- 指定 rm-248 的主机名 -->
<property>
<name>yarn.resourcemanager.hostname.rm-248</name>
<value>xxx-248</value>
</property>
<!-- 指定 rm-248 的 web 端地址 -->
<property>
<name>yarn.resourcemanager.webapp.address.rm-248</name>
<value>xxx-248:9088</value>
</property>
<!-- 指定 zookeeper 集群地址 -->
<property>
<name>hadoop.zk.address</name>
<value>xxx-246:2181,xxx-247:2181,xxx-248:2181</value>
</property>
<!-- 启用自动恢复 -->
<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
<!-- 指定 resourcemanager 的状态信息存储在 zookeeper 集群 -->
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
<!-- 忽略虚拟内存检查 -->
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
<property>
<name>yarn.nodemanager.pmem-check-enabled</name>
<value>false</value>
</property>
<!-- 每个 NodeManager 可用内存 -->
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>32768</value>
</property>
<!-- 每个任务可申请的最小/最大内存资源量 -->
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>2048</value>
</property>
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>32768</value>
</property>
<!-- 每个 NodeManager 可用 CPU 核心数 (虚拟 CPU 个数,推荐值与物理 CPU 核数数目相同) -->
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>16</value>
</property>
<!-- 单个任务可申请的最小/最大虚拟 CPU 个数 -->
<property>
<name>yarn.scheduler.minimum-allocation-vcores</name>
<value>1</value>
</property>
<property>
<name>yarn.scheduler.maximum-allocation-vcores</name>
<value>48</value>
</property>
<!-- 开启日志聚集功能 -->
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<!-- 设置日志聚集服务器地址 -->
<property>
<name>yarn.log.server.url</name>
<value>http://xxx-248:19888/jobhistory/logs</value>
</property>
<!-- 设置日志保留时间为 3 天 -->
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>259200</value>
</property>
<!-- 每天检查一次 -->
<property>
<name>yarn.log-aggregation.retain-check-interval-seconds</name>
<value>86400</value>
</property>
<!-- 应用执行完日志保留的时间 -->
<property>
<name>yarn.nodemanager.delete.debug-delay-sec</name>
<value>600</value>
</property>
<!-- 容器日志本地保存路径 -->
<property>
<name>yarn.nodemanager.log-dirs</name>
<value>/data/hadoop/log</value>
</property>
</configuration>
vi /etc/profile
# hadoop
export HADOOP_HOME=/opt/apps/hadoop-3.4.2
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
ansible cluster -m copy -a "src=/opt/apps/hadoop-3.4.2/etc/hadoop/capacity-scheduler.xml dest=/opt/apps/hadoop-3.4.2/etc/hadoop/"
anisble cluster -m copy -a "src=/opt/apps/hadoop-3.4.2/etc/hadoop/workers dest=/opt/apps/hadoop-3.4.2/etc/hadoop/"
anisble cluster -m copy -a "src=/opt/apps/hadoop-3.4.2/etc/hadoop/mapred-site.xml dest=/opt/apps/hadoop-3.4.2/etc/hadoop/"
anisble cluster -m copy -a "src=/opt/apps/hadoop-3.4.2/etc/hadoop/yarn-site.xml dest=/opt/apps/hadoop-3.4.2/etc/hadoop/"
anisble cluster -m copy -a "src=/opt/apps/hadoop-3.4.2/etc/hadoop/core-site.xml dest=/opt/apps/hadoop-3.4.2/etc/hadoop/"
anisble cluster -m copy -a "src=/opt/apps/hadoop-3.4.2/etc/hadoop/hdfs-site.xml dest=/opt/apps/hadoop-3.4.2/etc/hadoop/"
anisble cluster -m copy -a "src=/opt/apps/hadoop-3.4.2/etc/hadoop/hadoop-env.sh dest=/opt/apps/hadoop-3.4.2/etc/hadoop/"
anisble cluster -m copy -a "src=/opt/apps/hadoop-3.4.2/etc/hadoop/yarn-env.sh dest=/opt/apps/hadoop-3.4.2/etc/hadoop/"
# 创建目录
ansible cluster -m shell -a "mkdir -p /data/hadoop/data/{namenode,journal,datanode,tmp}"
anisble cluster -m shell -a "mkdir -p /data/hadoop/data/log"
# 赋权
ansible cluster -m shell -a "chown -R hadoop:hadoop /data/hadoop"
anisble cluster -m shell -a "chown -R hadoop:hadoop /opt/apps/hadoop-3.4.2"
# 停止所有 Hadoop 服务
stop-dfs.sh
# 初始化 HA 在 Zookeeper 中的状态
hdfs zkfc -formatZK
# 单节点
hdfs --daemon start zkfc
# 多节点
hdfs --workers --daemon start zkfc
# 启动
# 单节点启动(每个 JN 节点执行)
hdfs --daemon start journalnode
hdfs --daemon stop journalnode
# 批量启动(读取 workers 文件)
$HADOOP_HOME/bin/hdfs --workers --daemon start journalnode
# 验证 JournalNode 状态
curl http://xxx-246:8480/jmx
hdfs namenode -format
hdfs --daemon start namenode
# 所有备用 NN 节点执行
hdfs namenode -bootstrapStandby
# 所有备用 NN 节点执行
hdfs --daemon start namenode
hdfs haadmin -getAllServiceState
hdfs haadmin -transitionToActive nn-246
hdfs haadmin -transitionToActive --forcemanual nn-246
# 启动 NameNode、DataNode
start-dfs.sh
# 单节点启动 DataNode
hdfs --daemon start datanode
# 批量启动 DataNode
hdfs --workers --daemon start datanode
# 启动 ResourceManager、NodeManager
start-yarn.sh
# 查看节点状态
yarn rmadmin -getServiceState rm-246
mapred --daemon start historyserver
Hadoop 访问:http://192.168.xxx.xxx:9870
Yarn 访问:http://192.168.xxx.xxx:9088
hadoop fs -mkdir /tmp
hadoop fs -mkdir /spark-jars
hadoop fs -mkdir /spark-history
hadoop fs -mkdir /tmp/hadoop-yarn
hadoop fs -mkdir -p /user/hive
hadoop fs -mkdir -p /user/hive/tmp
hadoop fs -mkdir -p /user/hive/warehouse
hadoop fs -chmod g+w /tmp
hadoop fs -chmod g+w /spark-jars
hadoop fs -chmod g+w /spark-history
hadoop fs -chmod g+w /user/hive
hadoop fs -chmod g+w /user/hive/tmp
hadoop fs -chmod -R o+w /user/hive/tmp
hadoop fs -chmod -R g+w /user/hive/warehouse
hdfs dfs -chmod -R o+w /tmp/hadoop-yarn
hdfs dfs -chown -R hadoop:hive /user/hive
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.4.2.jar pi 10 100
# 1. 查看集群资源状态
yarn node-list
# 查看所有 NodeManager 节点状态
yarn node-status Node-Id
# 查看指定节点的资源使用情况
# 2. 查看任务列表与状态
yarn application -list
# 查看所有应用(任务)状态
yarn application -status application_1700000000000_0001
# 查看指定任务详情(替换为自身 application ID)
# 3. 杀死异常任务(任务卡顿、报错时使用)
yarn application -kill application_1700000000000_0001
# 4. 查看任务日志(关键,排查任务失败原因)
yarn logs -applicationId application_1700000000000_0001
# 查看整个任务的日志
yarn logs -applicationId application_1700000000000_0001 -containerId container_1700000000000_0001_01_000001
# 查看指定容器日志
# 直接 kill
ps -ef | grep hadoop-3.4.2 | grep -v grep | awk '{print $2}' | xargs kill -9

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online