基于Docker的中间件部署安装手册


title: 基于Docker的中间件部署安装手册
date: 2023-01-03 11:34:29
tags:

  • middleware
  • deploy
  • install

前提

本文通篇以流水账的形式叙述,主要是用来记录基于docker环境离线安装中间件的部署过程(命令行极速版,没有操作详解)。

软件基于 Ubuntu搭建,其他操作系统可能不适用

安装docker

按照操作系统要求,选取合适的docker版本,下载地址:docker下载地址

  1. 将下载好的软件包上传至服务器,并解压至/usr/local目录

    tar -zxvf docker-20.10.22.tgz -C /usr/local && mv /usr/local/docker/* /usr/bin
    rm -rf /usr/local/docker
    
  2. 进入/etc/systemd/system目录,并创建docker.service文件

    touch /etc/systemd/system/docker.service
    
  3. 编辑docker.service服务文件(关注ExecStart启动命令)

    [Unit]
    Description=Docker Application Container Engine
    Documentation=https://docs.docker.com
    After=network-online.target firewalld.service
    Wants=network-online.target
    
    [Service]
    Type=notify
    # the default is not to use systemd for cgroups because the delegate issues still
    # exists and systemd currently does not support the cgroup feature set required
    # for containers run by docker
    # docker默认数据目录为/var/lib/docker,使用df -hl /var/lib/docker查看磁盘空间是否足够,否则使用--graph重新指定docker的
    # 数据目录,若内网搭建镜像仓库,可使用--insecure-registry=127.0.0.1(镜像仓库ip)指向自己的镜像仓库
    ExecStart=/usr/bin/dockerd --selinux-enabled=false --graph=/home/docker
    ExecReload=/bin/kill -s HUP $MAINPID
    # Having non-zero Limit*s causes performance problems due to accounting overhead
    # in the kernel. We recommend using cgroups to do container-local accounting.
    LimitNOFILE=infinity
    LimitNPROC=infinity
    LimitCORE=infinity
    # Uncomment TasksMax if your systemd version supports it.
    # Only systemd 226 and above support this version.
    #TasksMax=infinity
    TimeoutStartSec=0
    # set delegate yes so that systemd does not reset the cgroups of docker containers
    Delegate=yes
    # kill only the docker process, not all processes in the cgroup
    KillMode=process
    # restart the docker process if it exits prematurely
    Restart=on-failure
    StartLimitBurst=3
    StartLimitInterval=60s
    
    [Install]
    WantedBy=multi-user.target
    
  4. docker.service文件添加执行权限

    chmod 755 /etc/systemd/system/docker.service
    
  5. 重新加载配置文件

    systemctl daemon-reload
    
  6. 启动docker

    systemctl start docker
    
  7. 设置开机启动

    systemctl enable docker.service
    
  8. 查看docker状态

    systemctl status docker.service
    

安装mysql集群(一主二从)

  1. 下载mysql镜像上传至服务器,并解压镜像包

    docker load -i mysql.tar 
    
  2. 创建挂载目录

    # 创建配置目录和数据目录
    mkdir -p /home/mysql/conf /home/mysql/data
    # 创建配置文件
    touch /home/mysql/conf/my.cnf
    
  3. 编辑my.cnf

    • 主节点配置
    [mysqld]
    # 设置server_id,集群中每个服务的server_id不能存在相同
    server-id = 1
    # 设置时区
    default-time-zone = '+08:00'
    pid-file = /var/run/mysqld/mysqld.pid
    socket = /var/run/mysqld/mysqld.sock
    # 容器数据目录
    datadir = /var/lib/mysql
    secure-file-priv= NULL
    # Disabling symbolic-links is recommended to prevent assorted security risks
    symbolic-links=0
    # Custom config should go here
    !includedir /etc/mysql/conf.d/
    max_connections=1000
    wait_timeout=28800
    interactive_timeout=28800
    ## 开启binlog
    log-bin=mysql-bin
    ## binlog缓存
    binlog_cache_size=1M
    ## binlog格式(mixed、statement、row,默认格式是statement)
    binlog_format=mixed
    ##设置字符编码为utf8mb4
    character-set-server = utf8mb4
    collation-server = utf8mb4_unicode_ci
    init_connect='SET NAMES utf8mb4'
    # 忽略大小写
    lower_case_table_names=1
    [client]
    default-character-set = utf8mb4
    [mysql]
    default-character-set = utf8mb4
    
    • 从节点配置
    # 设置server_id,注意要唯一
    server-id=2
    # 忽略大小写
    lower_case_table_names=1
    max_connections=1000
    wait_timeout=28800
    interactive_timeout=28800
    default-time_zone = '+8:00'
    # 开启binlog
    log-bin=mysql-slave-bin
    # relay_log配置中继日志
    relay_log=edu-mysql-relay-bin
    # 如果需要同步函数或者存储过程
    log_bin_trust_function_creators=true
    # binlog缓存
    binlog_cache_size=1M
    # binlog格式(mixed、statement、row,默认格式是statement)
    binlog_format=mixed
    #设置字符编码为utf8mb4
    character-set-server = utf8mb4
    collation-server = utf8mb4_unicode_ci
    init_connect='SET NAMES utf8mb4'
    slave_skip_errors=1062
    [client]
    default-character-set = utf8mb4
    [mysql]
    default-character-set = utf8mb4
    
  4. 运行实例

    • 主节点

      docker run -itd -p 3306:3306 \
      --name mysql-icp-master \
      --restart=always \
      -v /home/mysql/conf/my.cnf:/etc/mysql/my.cnf \
      -v /home/mysql/data:/var/lib/mysql \
      -e MYSQL_ROOT_PASSWORD=sillybilly@2022 \
      70325c69f1fe
      
    • 从节点1

      docker run -itd -p 3306:3306 \
      --name  mysql-icp-slave1 \
      --restart=always \
      -v /home/mysql/conf/my.cnf:/etc/mysql/my.cnf \
      -v /home/mysql/data:/var/lib/mysql \
      -e MYSQL_ROOT_PASSWORD=sillybilly@2022 \
      70325c69f1fe
      
    • 从节点2

      docker run -itd -p 3306:3306 \
      --name  mysql-icp-slave2 \
      --restart=always \
      -v /home/mysql/conf/my.cnf:/etc/mysql/my.cnf \
      -v /home/mysql/data:/var/lib/mysql \
      -e MYSQL_ROOT_PASSWORD=sillybilly@2022 \
      70325c69f1fe 
      
  5. 主从同步配置

    • 进入master节点容器,并执行mysql命令

      # 进入mysql命令列界面
      mysql -uroot -psillybilly@2022
      # 查看主节点信息
      SHOW MASTER STATUS;
      

      执行结果

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O0dTkdAW-1676527943448)(null)]

    • 进入mysql从节点,编辑同步配置

      # 配置连接的参数
      change master to master_host='10.10.33.102',master_user='root',master_password='sillybilly@2022',master_log_file='mysql-bin.000003',master_log_pos=62973466;
      

      master_host:主节点ip

      master_user:主节点登录用户名

      master_password:主节点mysql登录密码

      master_log_file:主节点日志文件,修改为master节点执行SHOW MASTER STATUS结果后的File字段

      master_log_pos:二进制文件开始位置,修改为master节点执行SHOW MASTER STATUS结果后的Position字段

      # 停止连接,如果一次成功无需使用该命令
      stop slave;
      # 重置连接
      reset slave;
      # 启动同步
      start slave;
      # 查看从节点状态是否成功
      show slave status;
      
      # 观察两项都为Yes时代表成功。
      # Slave_IO_Running: Yes
      # Slave_SQL_Running: Yes
      

      如果失败的话,需要执行stop slave并检查主节点的账号、密码,地址,pos等参数

安装minio集群

下载minio docker镜像包,并解压镜像,这里不过多赘述

单机版

启动docker实例

docker run -d \
-p 9000:9000 \
-p 19001:19001 \
--name minio-icp \
--restart=always \
-v /data/minio/data:/data \
-e "MINIO_ROOT_USER=sillybilly" \
-e "MINIO_ROOT_PASSWORD=sillybilly@2022" \
minio/minio server /data \
--console-address ":19001" \
--address ":9000"

MINIO_ROOT_USER:用户名

MINIO_ROOT_PASSWORD:密码

console-address:web控制台端口,可不指定

address:api访问端口

集群版

  1. 主机映射

    # 57、58、59三台服务器添加主机映射
    vim /etc/hosts
    
    # 在文件末尾添加以下信息 (实际需改成自己的ip地址,填内网ip,不能填公网ip)
    10.10.33.57 minio1
    10.10.33.58 minio2
    10.10.33.59 minio3
    
  2. 每个节点指定两个数据目录,例如/opt/data1,/opt/data2,最好是两块单独的磁盘

  3. 启动minio实例

    docker run -d --name minio-icp \
    --restart=always \
    --net=host \
    -e "MINIO_ROOT_USER=sillybilly" \
    -e "MINIO_ROOT_PASSWORD=sillybilly@2022" \
    -v /opt/data1:/data1 \
    -v /opt/data2:/data2 \
    minio/minio server \
    --address ":9000" \
    --console-address ":19001" \
    http://minio{1...3}/data{1...2}
    
  4. 访问10.10.33.57:19001验证

安装elasticsearch集群

iphostnamedefault-role
10.10.33.57node1master
10.10.33.58node2slave1
10.10.33.59node3slave2

elasticsearch8.x需要jdk17,因为我们大多数项目路使用jdk8,所以本次搭建使用elasticsearch:7.17.8

  1. 添加主机映射

    vim /etc/hosts
    
    # 添加主机映射关系至文件末尾
    10.10.33.57 node1
    10.10.33.58 node2
    10.10.33.59 node3
    
  2. 调整系统打开文件句柄数以及用户创建进程数

    vi /etc/security/limits.conf
    
    # 末尾添加
    * soft nofile 65536
    * hard nofile 131072
    * soft nproc 2048
    * hard nproc 4096
    
    #增大文件句柄数
    echo 'vm.max_map_count=262144' >>/etc/sysctl.conf
    # 立即生效
    sysctl -p
    
  3. 启动elasticsearch容器,拷贝es挂载目录

    # 先简单起容器,方便从容器中把配置拷贝出来
    docker run -d --name elasticsearch \
    -p 9200:9200 \
    -p 9300:9300 \
    -e  "discovery.type=single-node" \
    -e ES_JAVA_OPTS="-Xms256m -Xmx256m" \
    elasticsearch:7.17.8
    
    # 拷贝挂载目录
    docker cp elasticsearch:/usr/share/elasticsearch/config /data1/elasticsearch
    docker cp elasticsearch:/usr/share/elasticsearch/logs /data1/elasticsearch
    docker cp elasticsearch:/usr/share/elasticsearch/data /data1/elasticsearch
    docker cp elasticsearch:/usr/share/elasticsearch/plugins /data1/elasticsearch
    
  4. elasticsearch.yml配置

    • master

      # 设置集群名称,集群内所有节点的名称必须一致。
      cluster.name: icp-es-cluster
      # 设置节点名称,集群内节点名称必须唯一。
      node.name: node1
      # 表示该节点会不会作为主节点,true表示会;false表示不会
      node.master: true
      # 当前节点是否用于存储数据,是:true、否:false
      node.data: true
      # 索引数据存放的位置
      #path.data: /usr/share/elasticsearch/data
      # 日志文件存放的位置
      #path.logs: /usr/share/elasticsearch/logs
      # 需求锁住物理内存,是:true、否:false
      #bootstrap.memory_lock: true
      # 监听地址,用于访问该es
      network.host: 0.0.0.0
      # es对外提供的http端口,默认 9200
      http.port: 19200
      # TCP的默认监听端口,默认 9300
      transport.tcp.port: 19300
      # 设置这个参数来保证集群中的节点可以知道其它N个有master资格的节点。默认为1,对于大的集群来说,可以设置大一点的值(2-4)
      discovery.zen.minimum_master_nodes: 1
      # es7.x 之后新增的配置,写入候选主节点的设备地址,在开启服务后可以被选为主节点
      discovery.seed_hosts: ["10.10.33.57:19300", "10.10.33.58:19300","10.10.33.59:19300"]
      discovery.zen.fd.ping_timeout: 1m
      discovery.zen.fd.ping_retries: 5
      # es7.x 之后新增的配置,初始化一个新的集群时需要此配置来选举master
      cluster.initial_master_nodes: ["node1"]
      # 是否支持跨域,是:true,在使用head插件时需要此配置
      http.cors.enabled: true
      # “*” 表示支持所有域名
      http.cors.allow-origin: "*"
      ingest.geoip.downloader.enabled: false
      
    • slave1

      # 设置集群名称,集群内所有节点的名称必须一致。
      cluster.name: icp-es-cluster
      # 设置节点名称,集群内节点名称必须唯一。
      node.name: node2
      # 表示该节点会不会作为主节点,true表示会;false表示不会
      node.master: true
      # 当前节点是否用于存储数据,是:true、否:false
      node.data: true
      # 索引数据存放的位置
      #path.data: /usr/share/elasticsearch/data
      # 日志文件存放的位置
      #path.logs: /usr/share/elasticsearch/logs
      # 需求锁住物理内存,是:true、否:false
      #bootstrap.memory_lock: true
      # 监听地址,用于访问该es
      network.host: 0.0.0.0
      # es对外提供的http端口,默认 9200
      http.port: 19200
      # TCP的默认监听端口,默认 9300
      transport.tcp.port: 19300
      # 设置这个参数来保证集群中的节点可以知道其它N个有master资格的节点。默认为1,对于大的集群来说,可以设置大一点的值(2-4)
      discovery.zen.minimum_master_nodes: 1
      # es7.x 之后新增的配置,写入候选主节点的设备地址,在开启服务后可以被选为主节点
      discovery.seed_hosts: ["10.10.33.57:19300", "10.10.33.58:19300","10.10.33.59:19300"]
      discovery.zen.fd.ping_timeout: 1m
      discovery.zen.fd.ping_retries: 5
      # es7.x 之后新增的配置,初始化一个新的集群时需要此配置来选举master
      cluster.initial_master_nodes: ["node1"]
      # 是否支持跨域,是:true,在使用head插件时需要此配置
      http.cors.enabled: true
      # “*” 表示支持所有域名
      http.cors.allow-origin: "*"
      ingest.geoip.downloader.enabled: false
      
    • slave2

      # 设置集群名称,集群内所有节点的名称必须一致。
      cluster.name: icp-es-cluster
      # 设置节点名称,集群内节点名称必须唯一。
      node.name: node3
      # 表示该节点会不会作为主节点,true表示会;false表示不会
      node.master: true
      # 当前节点是否用于存储数据,是:true、否:false
      node.data: true
      # 索引数据存放的位置
      #path.data: /usr/share/elasticsearch/data
      # 日志文件存放的位置
      #path.logs: /usr/share/elasticsearch/logs
      # 需求锁住物理内存,是:true、否:false
      #bootstrap.memory_lock: true
      # 监听地址,用于访问该es
      network.host: 0.0.0.0
      # es对外提供的http端口,默认 9200
      http.port: 19200
      # TCP的默认监听端口,默认 9300
      transport.tcp.port: 19300
      # 设置这个参数来保证集群中的节点可以知道其它N个有master资格的节点。默认为1,对于大的集群来说,可以设置大一点的值(2-4)
      discovery.zen.minimum_master_nodes: 1
      # es7.x 之后新增的配置,写入候选主节点的设备地址,在开启服务后可以被选为主节点
      discovery.seed_hosts: ["10.10.33.57:19300", "10.10.33.58:19300","10.10.33.59:19300"]
      discovery.zen.fd.ping_timeout: 1m
      discovery.zen.fd.ping_retries: 5
      # es7.x 之后新增的配置,初始化一个新的集群时需要此配置来选举master
      cluster.initial_master_nodes: ["node1"]
      # 是否支持跨域,是:true,在使用head插件时需要此配置
      http.cors.enabled: true
      # “*” 表示支持所有域名
      http.cors.allow-origin: "*"
      ingest.geoip.downloader.enabled: false
      
  5. 初始化容器

    docker run -d \
      --name=elasticsearch-icp \
      --restart=always \
      --network=host \
      -v /data1/elasticsearch/config:/usr/share/elasticsearch/config \
      -v /data1/elasticsearch/logs:/usr/share/elasticsearch/logs \
      -v /data1/elasticsearch/data:/usr/share/elasticsearch/data \
      -v /data1/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
      elasticsearch:7.17.8
    
  6. 验证

    # 浏览器输入地址 查看3个节点是否都加入集群
    http://10.10.33.102:19200/_cat/nodes
    
  7. QA

    如果出现新启动的节点无法加入集群,报错例如: "Caused by: org.elasticsearch.cluster.coordination.CoordinationStateRejectedException: This node previously joined a cluster with UUID [NR0YxxfATD2Y1q4PnhXfoA] and is now trying to join a different cluster with UUID [3d1d4hnwR2e5kU9yYH2K5w]. This is forbidden and usually indicates an incorrect discovery or cluster bootstrapping configuration. Note that the cluster UUID persists across restarts and can only be changed by deleting the contents of the node's data paths [] which will also remove any data held by this node."

​ 可以删除/data1/elasticsearch/data中的数据,再次重启容器

安装kibana(单机)

  1. kibana.yml配置

    #Kibana的映射端口
    server.port: 15601
    #网关地址
    server.host: "0.0.0.0"
    #Kibana实例对外展示的名称
    server.name: "kibana"
    #Elasticsearch的集群地址,也就是说所有的集群IP
    elasticsearch.hosts: ["http://10.10.33.57:19200","http://10.10.33.58:19200","http://10.10.33.59:19200"]
    #设置页面语言,中文使用zh-CN,英文使用en
    i18n.locale: "zh-CN"
    xpack.monitoring.ui.container.elasticsearch.enabled: true
    # es用户名、密码
    elasticsearch.username: ""
    elasticsearch.password: ""
    
  2. 容器启动

    docker run -itd \
    --network=host \
    -v /data1/kibana/kibana.yml:/usr/share/kibana/config/kibana.yml  \
    --name kibana-icp \
    kibana:7.17.8
    

安装only-office(单机)

下载only-office镜像包,这里以onlyoffice/documentserver:7.1为例

  1. 创建挂载目录

    # 文档日志
    mkdir -p /home/onlyoffice/documentserver/logs
    # 证书
    mkdir -p /home/onlyoffice/documentserver/data
    # 文件缓存
    mkdir -p /home/onlyoffice/documentserver/lib
    # 数据库
    mkdir -p /home/onlyoffice/documentserver/db
    
  2. 启动实例

    docker run -i -t -d \
    --name office-icp \
    -p 7001:80 \
    --restart=always \
    -v /home/onlyoffice/documentserver/logs:/var/log/onlyoffice \
    -v /home/onlyoffice/documentserver/data:/var/www/onlyoffice/Data \
    -v /home/onlyoffice/documentserver/lib:/var/lib/onlyoffice \
    -v /home/onlyoffice/documentserver/db:/var/lib/postgresql \
    onlyoffice/documentserver:7.1
    

安装redis主从

ipportrole
10.10.33.5816379master
10.10.33.5826379sentinel
10.10.33.5916379slave
10.10.33.5926379sentinel
10.10.33.6016379slave
10.10.33.6026379sentinel

下载redis镜像包,安装版本:7.0.4

新增主、从节点redis.conf配置

# bind 127.0.0.1

# 开启集群 这里是主从 不需要开启
#cluster-enabled yes

# 默认yes,开启保护模式,限制为本地访问
protected-mode no

# 默认no,改为yes意为以守护进程方式启动,可后台运行,除非kill进程,改为yes会使配置文件方式启动redis失败
daemonize no

dir ./

appendonly yes

logfile "access.log"

# redis密码配置
requirepass sillybilly@2022

# 修改端口号
port 16379

############################以下配置为从服务器配置,主服务器无需配置#################

#下面的IP和端口号为表示为redis主服务器
# replicaof 10.10.33.58 16379
# 如果主服务器配置了密码,则需要添加如下命令(zsrj@2022表示redis主服务器的密码)
# masterauth sillybilly@2022

新增哨兵sentinel.conf配置

# 哨兵使用的端口号,默认是26379,可以更改
port 26379
# 文件存储位置
dir "/"
# 日志保存的文件路径(该文件路径必须存在)
logfile "/sentinel.log"
# 哨兵监控IP为10.10.33.58端口号为16379的redis主服务器,主服务器名称为redis-master,最后的数字表示数量,例如3台哨兵,其中有2台哨兵认为redis主服务器已经宕机,则主机已经宕机,否则不认为redis的主服务器宕机
sentinel monitor redis-master 10.10.33.58 16379 2
# 在指定的毫秒数内,若主节点没有应答哨兵的 PING 命令,此时哨兵认为服务器主观下线,默认时间为 30 秒。
sentinel down-after-milliseconds redis-master 5000

# 如果主服务器配置了密码,则哨兵也必须配置密码,否则哨兵无法对主从服务器进行监控,该密码与主服务器密码一致
sentinel auth-pass redis-master sillybilly@2022

# redis哨兵密码
requirepass sillybilly@2022

创建并启动主、从容器

# 主节点 10.10.33.58
docker run --net host --name redis-icp-master \
-v /home/redis/redis.conf:/redis.conf \
-v /home/redis/data:/data \
--privileged=true -d redis:7.0.4 redis-server /redis.conf

# 从节点 10.10.33.59
docker run --net host --name redis-icp-slave1 \
-v /home/redis/redis.conf:/redis.conf \
-v /home/redis/data:/data \
--privileged=true -d redis:7.0.4 redis-server /redis.conf

# 从节点 10.10.33.60
docker run --net host --name redis-icp-slave2 \
-v /home/redis/redis.conf:/redis.conf \
-v /home/redis/data:/data \
--privileged=true -d redis:7.0.4 redis-server /redis.conf

创建并启动哨兵

# 启动从节点1哨兵 10.10.33.58
docker run --net host --name redis-icp-sentinel1 \
-v /home/redis/sentinel.conf:/sentinel.conf \
-d redis:7.0.4  redis-sentinel /sentinel.conf

# 启动从节点2哨兵 10.10.33.59
docker run --net host --name redis-icp-sentinel2 \
-v /home/redis/sentinel.conf:/sentinel.conf \
-d redis:7.0.4  redis-sentinel /sentinel.conf

# 启动从节点3哨兵 10.10.33.60
docker run --net host --name redis-icp-sentinel3 \
-v /home/redis/sentinel.conf:/sentinel.conf \
-d redis:7.0.4  redis-sentinel /sentinel.conf

环境验证

# 进入主节点容器内部 containerId 为58环境master节点容器id
docker exec -it [containerId] bash
# 进入redis命令列界面
redis-cli -a sillybilly@2022 -p 16379
# 查看主从信息
info replication

# 进入哨兵容器内部 containerId 为任意环境哨兵容器id
docker exec -it [containerId] bash
# 进入redis命令列界面
redis-cli -a sillybilly@2022 -p 16379
# 查看哨兵监控信息
info sentinel

未完待补充

附录

docker命令

# 获取Docker中运行的组件的内网IP
docker inspect --format='{{.NetworkSettings.IPAddress}}' 【容器实例名称】

磁盘挂载

新建分区
# 列出可用磁盘
fdisk -l
# 创建一个新的磁盘分区 使用命令:"fdisk 磁盘名称" (仅限2T磁盘的分区)
# 按提示依次操作
fdisk /dev/sdb
格式化硬盘
mkfs.ext4 /dev/sdb1
查询硬盘的UUID
sudo blkid
UUID写入配置
sudo vim /etc/fstab

# 文件末尾添加磁盘信息 
# UUID为上一步查询的结果 /data为挂载目录
# ext4:文件系统类型 defaults:挂载参数
# 第五个字段为dump 参数 用检查一个文件系统是否应该进行 dump 备份。不需要就设置为 0,如果需要每天备份,设置为 1,不定期备份,设置为 2
# 第六个字段为开机检查分区的次序。对于根分区,这个值为 1,表示优先。其它文件系统可以设置为 2,表示次优,如果为 0 或没有设置,开机跳过此文件系统的检查
UUID=d6644d06-0532-49d7-b7d4-5875b555a29c /data ext4  defaults 0 1

# 退出编辑 重启
reboot
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值