eureka,springboot admin搭建

上一篇:springcloud多模块项目搭建(一)

创建maven父工程

父工程只是用户汇总eureka,springcloud config sever等之类的基础设施,通过maven创建即可。

  1. idea -> file -> new -> project,选maven方式,直接点击next
    在这里插入图片描述
  2. 输入GroupID,AritfactId,Version,点击next
    在这里插入图片描述
  3. 输入工程名和本地存放地址,点击finish
    在这里插入图片描述
  4. 生成父工程后可删除src目录和pom.xml文件

创建eureka模块

  1. 点击父工程根目录,右键 new -> Module,选择Spring Initializr,点击next
    在这里插入图片描述
  2. 设置对应的选项,点击next
    在这里插入图片描述
  3. 左上角选择Spring Boot版本,这里选用的是2.1.8,并添加Eureka Sever依赖(由于springboot和springcloud间的版本依赖关系较为混乱,不同版本之间有时候互不兼容,这里让idea自动去生成两者的版本映射),我后来做过eureka版本升级,当前我用的spring boot版本是2.4.6,点击next
    在这里插入图片描述
  4. 检查配置后点击finish
    在这里插入图片描述
    生成后的文件目录和pom依赖如下,会自动生成当前springboot适合的springcloud版本,关于两者的版本之间的映射关系可以在网上查找。springcloud各版本之间是有区别的,这里生成的eureka的aritifactId为spring-cloud-starter-netflix-eureka-server,springboot1x对应的springcloud版本依赖的eureka的aritifactId为spring-cloud-starter-eureka-server,不同版本之间依赖的包名有会不一样,给版本升级、维护带来一定的困难和风险。
    在这里插入图片描述
  5. 在resource目录下分别添加application.yml, application-server1.yml, application-server2.yml 配置文件,配置信息如下:
    application.yml代码配置:
    spring.profiles.active属性可以指定引入的配置文件
spring:
  application:
    name: eureka-service
  # 安全认证相关配置
  security:
    basic:
      enabled: true
    user:
      # eureka管理后台登录用户名
      name: admin
      # eureka管理后台登录用户密码
      password: 1234567
  profiles:
    # 部署eureka server1时引入server1配置文件,部署eureka server2时引入server2配置文件,来启动不同的eureka实例
    active: eurekaServer1

server:
  port: 8090
  servlet:
    # 配置访问路径,如果配置该选项,则访问eureka server管理平台,访问路径中需要多加上 context-path 配置的路径
    # eureka client 配置 eureka.client.service-url.defaultZone 时也要多加上 context-path 配置的路径
    context-path: /eureka

application-eurekaServer1.yml代码配置:

eureka:
  server:
    # 关闭自我保护机制,默认值开启自我保护机制
    # 自我保护机制:默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。
    # 当Eureka Server在短时间内丢失过多的客户端时(可能发生了网络故障),Eureka Server将进入自我保护模式,不再注销任何微服务,
    # 网络故障回复后Eureka Server会自动退出自我保护模式。如果Eureka Server和客户端是部署在同一局域网下,网络故障的可能性较低,可以关闭自我保护机制。
    enable-self-preservation: false
    # 清理无效节点的时间间隔(单位毫秒,默认是60*1000)
    eviction-interval-timer-in-ms: 60000
  instance:
    # hostname 服务实例唯一标识,不能重复,
    # 这里配置的hostname必须要在部署服务器的 /etc/hosts 文件中绑定对应的主机名,否则分布式部署的时候会导致 unavailable-replicas
    hostname: eurekaServer1
    # preferIpAddress=true时,将ipAddress配置的IP地址注册到eureka server,
    # preferIpAddress=false时,将eureka.instance.hostname注册到eureka server
    prefer-ip-address: false
  client:
    # 是否向注册中心注册自己,设为false则能从集群注册中心发现其它服务的实例,但自己无法被其它服务所发现
    # eureka server单机部署时该项配置可设置为false
    # eureka server分布式部署时该项配置必须设置为true,否则不同eureka server实例之间无法互相备份
    register-with-eureka: true
    # 是否从集群注册中心拉取注册服务信息
    # eureka server单机部署时该项配置可设置为false
    # eureka server分布式部署时该项配置必须设置为true,否则不同eureka server实例之间无法互相备份
    fetch-registry: true
    service-url:
      # register self to eureka_server1, 格式为http://username:password@ip:port/eureka
      defaultZone: http://admin:1234567@eurekaServer2:8090/eureka/eureka

application-eurekaServer2.yml代码配置:

eureka:
  server:
    # 关闭自我保护机制,默认值开启自我保护机制
    # 自我保护机制:默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。
    # 当Eureka Server在短时间内丢失过多的客户端时(可能发生了网络故障),Eureka Server将进入自我保护模式,不再注销任何微服务,
    # 网络故障回复后Eureka Server会自动退出自我保护模式。如果Eureka Server和客户端是部署在同一局域网下,网络故障的可能性较低,可以关闭自我保护机制。
    enable-self-preservation: false
    # 清理无效节点的时间间隔(单位毫秒,默认是60*1000)
    eviction-interval-timer-in-ms: 60000
  instance:
    # hostname 服务实例唯一标识,不能重复,
    # 这里配置的hostname必须要在部署服务器的 /etc/hosts 文件中绑定对应的主机名,否则分布式部署的时候会导致 unavailable-replicas
    hostname: eurekaServer2
    # preferIpAddress=true时,将ipAddress配置的IP地址注册到eureka server,
    # preferIpAddress=false时,将eureka.instance.hostname注册到eureka server
    prefer-ip-address: false
  client:
    # 是否向注册中心注册自己,设为false则能从集群注册中心发现其它服务的实例,但自己无法被其它服务所发现
    # eureka server单机部署时该项配置可设置为false
    # eureka server分布式部署时该项配置必须设置为true,否则不同eureka server实例之间无法互相备份
    register-with-eureka: true
    # 是否从集群注册中心拉取注册服务信息
    # eureka server单机部署时该项配置可设置为false
    # eureka server分布式部署时该项配置必须设置为true,否则不同eureka server实例之间无法互相备份
    fetch-registry: true
    service-url:
      # register self to eureka_server1, 格式为http://username:password@ip:port/eureka
      defaultZone: http://admin:1234567@eurekaServer1:8090/eureka/eureka
  1. 在springboot启动类上加上 @EnableEurekaServer注解
    启动工程,会报:com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server 的错误,是由于springboot2x以上的版本,的security默认启用了csrf检验,要在eurekaServer端配置security的csrf检验为false,改动如下:
    pom引入依赖:
        <!-- springboot 安全相关依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

添加WebSecurityConfig 类,继承WebSecurityConfigurerAdapter,重写configure 方法,在configure方法里关闭csrf

package com.wangzhongxing.springcloud.eureka;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * @Auther: wangzhongxing
 * @Date: 2019/9/16 16:43
 * @Description: springboot2x以上的版本,的security默认启用了csrf检验,要在eurekaServer端配置security的csrf检验为false
 *
 */
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        super.configure(http);
    }
}
  1. 本地模拟多节点集群,hosts文件绑定
    #eureka模拟集群绑定hosts
    127.0.0.1 eurekaServer1
    127.0.0.1 eurekaServer2

idea配置两个springboot启动类,将application.yml中的spring.profiles.active属性值设为server1,启动第一个启动类,在将spring.profiles.active属性值设为server2,启动第二个启动类,访问
http://localhost:8761/ 和 http://localhost:8762/ ,输入用户名密码登录eureka管理界面。
在这里插入图片描述

pom文件完整配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wangzhongxing</groupId>
    <artifactId>springcloud-eureka</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    <name>springcloud-eureka</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>2020.0.2</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- springboot 安全认证相关依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.19.1</version>
                <configuration>
                    <!--默认关掉单元测试 -->
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!-- 指定该Main Class为全局的唯一入口 -->
                    <mainClass>com.wangzhongxing.springcloud.eureka.SpringcloudEurekaApplication</mainClass>
                    <layout>ZIP</layout>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

创建springboot admin模块

  1. 点击父工程根目录,右键 new -> Module,选择Spring Initializr,点击next
    在这里插入图片描述
  2. 输入Group, Artifact, Packaging选择war,点击next
    在这里插入图片描述
  3. 选择Spring Boot Admin(Server)相关依赖,Spring Boot版本选择2.1.8,点击next
    在这里插入图片描述
  4. 设置模块名称和存储路径,点击Finish
    在这里插入图片描述
    spring boot admin 2.1.5 官方文档

集成Spring Security

spring boot admin默认不提供身份验证和授权机制,需要自己集成Spring Security实现登录权限管控。

  1. 在生成好的pom文件中添加springboot 安全认证相关依赖,设置登录监控管理平台的账号和密码,不然默认是免密码登录的,spring-boot-starter-security的版本号会自动根据springboot的版本选取
        <!-- springboot 安全认证相关依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
  1. 添加安全配置类SpringBootAdminWebSecurityConfig,不然启动client后授权会失败
package com.wangzhongxing.springbootadmin;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * @Auther: wangzhongxing
 * @Date: 2019/9/16 16:43
 * @Description: springboot2x以上的版本,默认启用了csrf检验,要在springboot admin端配置security的csrf检验为false
 *
 */
@EnableWebSecurity
public class SpringBootAdminWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        successHandler.setTargetUrlParameter("redirectTo");
        successHandler.setDefaultTargetUrl(adminContextPath + "/");

        http.authorizeRequests()
                // 	授予对所有静态资产和登录页面的公共访问权限
                .antMatchers(adminContextPath + "/assets/**").permitAll()
                .antMatchers(adminContextPath + "/login").permitAll()
                // 其他所有请求都必须经过验证
                .anyRequest().authenticated()
                .and()
                // 配置登录和注销
                .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
                .logout().logoutUrl(adminContextPath + "/logout").and()
                // 启用HTTP基本支持。这是Spring Boot Admin Client注册所必需的。
                .httpBasic().and()
                // 使用Cookies启用CSRF保护
                .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .ignoringAntMatchers(
                        // 禁用CRSF保护Spring Boot Admin Client用于注册的端点。
                        adminContextPath + "/instances",
                        // 对执行器端点禁用CRSF-Protection。
                        adminContextPath + "/actuator/**"
                );
        // @formatter:on
    }
}
  1. application.yml添加如下配置:
spring:
  application:
    # 应用名
    name: springboot-admin-server
  # 安全认证相关配置
  security:
    basic:
      enabled: true
    user:
      # eureka管理后台登录用户名
      name: admin
      # eureka管理后台登录用户密码
      password: 123456

# 定义日志文件输出路径,服务端不配置该路径监控界面显示红字提示:Fetching logfile failed.Request failed with status code 404
logging:
  file: /opt/apache-tomcat-8.5.28/logs/openapiGateway/springbootAdmin.log

server:
  port: 8763

在springboot启动类上加上@EnableAdminServer注解,运行启动类,
访问:http://localhost:8763
输入登录账号密码,界面信息如下:
在这里插入图片描述
当前没有任何监控中的应用

创建监控的client应用

  1. client添加spring-boot-admin-starter-client依赖,在上一篇创建的springcloud模板工程的web模块中添加添加相关的配置,web模块的pom文件中添加依赖(springboot版本是2.1.8.RELEASE):
        <!-- spring boot admin client相关依赖 -->
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
            <version>2.1.5</version>
        </dependency>
  1. 在web模块下添加一个application-springbootadmin.yml文件用于配置springboot admin,在application.yml的active配置中引入application-springbootadmin.yml相关配置,application-springbootadmin.yml完整配置信息如下:
spring:
  # spring boot admin配置
  boot:
    admin:
      client:
        # spring boot admin server地址,如果spring boot server是部署到外部Tomcat中,需要带上Tomcat中webapp的路径
        url: http://ip:8080/springbootAdmin
        # spring boot admin管理平台登录账号名
        username: admin
        # spring boot admin管理平台登录账号密码
        password: 123456
        instance:
          # Base url for computing the service-url to register with. The path is inferred at runtime, and appended to the base url.
          # spring boot admin client的地址,该属性值与client的hostname, server.port有关,与访问路径无关
          # client部署在Tomcat时也只要配置hostname:port即可,无需配置Tomcat的访问路径
          service-base-url: http://ip:8080
          metadata:
            # These two are needed so that the server can access the protected client endpoints
            user.name: admin
            user.password: 123456

# spring boot admin 监控信息相关配置
management:
  health:
    # 忽略redis健康检查,只要有一项的健康检查不通过,系统整体就是down的状态,会触发报警邮件
    redis:
      enabled: false
  endpoints:
    web:
      exposure:
        # actuator开放端点配置,默认只开放health,info两个端点,*表示监控所有端点(必须加单引号,不然启动会报错)
        include: '*'
  endpoint:
    logfile:
      # spring boot admin  client不配置日志文件路径(同时配置logback-spring.xml对应的日志输出配置,否则无法输出日志),
      # 控制台上的Logging模块下的Logfile会报错:Fetching logfile failed.Request failed with status code 404
      external-file: /opt/apache-tomcat-8.5.28/logs/springbootAdmin.log
      enabled: true
    health:
      # Always show full health details.
      show-details: always

在logback-spring.xml文件中添加日志打印相关的配置:

    <!-- springboot admin日志 appender : 按照每天生成日志文件 -->
    <appender name="SPRINGBOOT-ADMIN-LOGGER" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <append>true</append>
        <!-- 过滤器,只记录 info 级别的日志 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>info</level>
        </filter>
        <!-- 日志名称 -->
        <file>${logging.path}/springbootAdmin.log</file>
        <!-- 每天生成一个日志文件,保存30天的日志文件 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名:按天回滚 daily -->
            <FileNamePattern>${logging.path}/springbootAdmin.log.%d{yyyy-MM-dd}
            </FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>7</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <!-- 编码 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
  1. 启动client应用,刷新spring boot admin监控平台,发现已经监控到一个应用了
    在这里插入图片描述
    点击Wallboard,选择对应的应用,可以监控到系统、JVM、springboot配置等相关的内容。
    在这里插入图片描述

服务下线发送邮件通知

  1. spring boot admin server pom文件引入mail相关依赖:
        <!-- spring boot admin发送监控邮件相关依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
  1. 在spring bootadmin server web模块下的application-springbootadmin.yml文件中增加发送邮件相关的配置,完整配置如下:
spring:
  application:
    name: springboot-admin-server
  # spring security安全认证相关配置
  security:
    basic:
      enabled: true
    user:
      # eureka管理后台登录用户名
      name: admin
      # eureka管理后台登录用户密码
      password: 123456
  # spring boot admin发送监控邮件配置
  mail:
    # 邮箱服务器地址
    host: smtp.163.com
    # 发送邮件的邮箱账号
    username: xxx@163.com
    # 发送邮件的邮箱密码(授权码)
    password: xxx
    properties:
      mail:
        smtp:
          # 安全认证,默认为true
          auth: true
          # starttls:对纯文本通信协议的扩展。它提供一种方式将纯文本连接升级为加密连接(TLS或SSL)
          starttls:
            # #关闭ssl加密
            enable: false
            required: false
    # 邮件服务器端口号,根据邮件服务商该端口号会有所不同
#    port: 80
    protocol: smtp
  boot:
    admin:
      notify:
        mail:
          # 邮件发送发
          from: xxx@163.com
          # 邮件接收方
          to: xxx@163.com
          enabled: true
          # List of changes to ignore. Must be in Format OLD:NEW, for any status use * as wildcard,e.g. *:UP or OFFLINE:*,
          # default value UNKNOWN:UP
          ignore-changes: UNKNOWN:UP,UNKNOWN:OFFLINE,OFFLINE:UP
#      monitor:
        # 被监控的应用信息的过期时间,单位毫秒,默认10S
#        status-lifetime:


# 定义日志文件输出路径,服务端不配置该路径监控界面显示红字提示:Fetching logfile failed.Request failed with status code 404
logging:
  file: /opt/apache-tomcat-8.5.28/logs/springbootAdmin.log


# 内置Tomcat时需要配置端口号,外部Tomcat部署无需配置
#server:
#  port: 8080
#  servlet:
#    context-path: /springbootAdmin
  1. 启动client应用,再停掉client应用,就会收到服务上线、下线的邮件通知
    在这里插入图片描述

springcloud多模块项目搭建(一)

源码下载地址

https://gitee.com/joshua2019/springcloud-basic-template

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Spring Boot Admin是用于监控基于Spring Boot的应用程序的工具。它建立在Spring Boot Actuator的基础上,并提供了一个简洁的可视化WEB UI界面。 要搭建Spring Boot Admin,首先需要重启Spring Boot Admin Server和Spring Boot Admin Client应用程序。在Spring Boot启动类上添加@EnableAdminServer注解,并配置application.properties文件。 在Client应用中,需要引入相关依赖,并在配置文件中设置Spring Boot Admin Server的注册地址,并将监控端口暴露给Spring Boot Admin Server访问。 启动测试后,可以通过Spring Boot Admin的WEB UI界面来监控和管理Spring Boot应用程序。 总结起来,Spring Boot Admin是一个用于监控和管理基于Spring Boot的应用程序的工具,通过提供简洁的WEB UI界面,使得对应用程序的监控变得更加方便和直观。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【SpringBoot框架篇】13.使用springboot adminspringboot应用进行监控](https://blog.csdn.net/ming19951224/article/details/107138845)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Spring Boot Admin 详解(Spring Boot 2.0,基于 Eureka 的实现)](https://blog.csdn.net/zzg_1990/article/details/84326958)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值