spring cloud 学习笔记

单体应用存在的问题

业务的发展,开发变得复杂,修改新增功能需要对整个系统精选测试,重新部署,一个模块出现问题很可能让整个系统崩溃,且模块内容过于复杂,耦合性太高。

分布式,集群

集群:一台服务器无法负荷高并发的数据访问量,那么久设置多个服务器一起分担压力(物理层面),多个人干同一件事情来分摊压力

分布式:讲一个复杂问题拆分成若干个简单的小问题,讲一个大型的项目架构拆分成若干个微服务来协同完成(软件设计层面),将庞大的工作拆分成若干个小步骤,分别有不同的人完成这些小步骤,最终将所有小步骤组合成整个项目

Spring Cloud

核心组件

  • 服务治理Eureka
  • 服务通信Ribbon Feign
  • 服务网关Zuul
  • 服务跟踪Zipkin
  • 服务监控Actuator
  • 服务配置Config
  • 服务容错Hystrix

服务治理核心由三部分组成:
- 服务提供者
- 服务消费者
- 注册中心
在分布式系统中,每个微服务在启动时,将自己的信息存储在注册中心,叫做服务注册
服务消费者从注册中心获取服务提供者的网络信息,通过该信息调用服务,叫做服务发现

Spring Cloud的服务治理使用Eureka来实现,Eureka是Netfix开源的基于REST的服务治理解决方案,Spring Cloud集成了Eureka,提供了服务注册和服务发现的功能,可以喝基于Spring Boot搭建的微服务应用轻松完成整合,开箱即用,Spring Cloud Eureka

Spring Cloud Eureka

  • Eureka Server 注册中心
  • Eureka Client,所有要进行注册的微服务通过Eureka Client连接到Eureka Server,完成注册

创建父工程

创建springboot父工程,添加pom依赖,需要注意的是springboot版本需要与spring cloud版本相适应,详情查看官网

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>springcloud-learn</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
    </parent>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR8</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

Eureka Server代码实现

在父工程下创建子工程eureka-server,添加pom依赖

<dependencies>
     <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
         <version>2.2.5.RELEASE</version>
     </dependency>
 </dependencies>

编写application.yml

server:
  port: 8761

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone:http://localhost:8761/eureka

属性说明:

server.port:当前Eureka Server的服务端口
eureka.client.register-with-eureka:是否将当前的Eureka Server服务作为客户端进行注册
eureka.client.fetch-fegistry:是否获取其他Eureka Server服务的数据
eureka.client.service-url.defaultZone:注册中心的访问的地址

创建启动类

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }

}

@EnableEurekaServer:声明该类是一个Eureka Server微服务,提供服务注册和服务发现功能

测试
在这里插入图片描述

Eureka Client 代码实现

  • 创建子模块,添加pom依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
</dependencies>
  • 添加配置文件application.yml,以及相关配置
server:
  port: 8010
spring:
  application:
    name: provide
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
    instance:
      prefer-ip-address: true

属性说明

spring.application.name:当前服务注册在Eureka Server上的名称
eureka.client.service-url.defaultZone:注册中心的访问地址
eureka.instance.prefer-ip-address:是否将当前服务的ip注册到Eureka Server

  • 创建启动类
@SpringBootApplication
public class EurekaClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApplication.class,args);
    }
}

RestTemplate

  • 什么是RestTemplate
    resttemplate是spring框架提供的基于REST的服务组件,自层是对http请求级响应惊醒了封装,提供了许多访问REST服务的方法,可以简化代码开发。
  • 如何使用RestTemplat
  1. 创建子工程,不需要添加额外依赖
  2. 添加配置类,将restTemplate配置为bean注入ioc容器
@Configuration
public class Config {
    @Bean
    public RestTemplate restTemplate(){
        return  new RestTemplate();
    }
}
  1. 添加启动类
  2. 添加实体类Student
  3. 调用
@RestController
@RequestMapping("/rest")
public class RestTemplateController {
    @Autowired
    private RestTemplate restTemplate;
    String url_base="http://localhost:8010/student/";
    @GetMapping("/findAll")
    public Collection<Student> findAll() {
        return restTemplate.getForEntity(url_base+"findAll", Collection.class).getBody();
    }
    @GetMapping("/findAll2")
    public Collection<Student> findAll2() {
        return restTemplate.getForObject(url_base+"findAll", Collection.class);
    }
    @GetMapping("/2/{id}")
    public Student findById(@PathVariable("id") long id) {
        return restTemplate.getForEntity(url_base+"{id}",Student.class,id).getBody();
    }
    @GetMapping("/{id}")
    public Student findById2(@PathVariable("id") long id) {
        return restTemplate.getForObject(url_base+"{id}",Student.class,id);
    }
    @PostMapping("/save")
    public void save(@RequestBody Student student) {
        restTemplate.postForEntity(url_base+"save",student,Void.class);
    }
    @PostMapping("2/save")
    public void save2(@RequestBody Student student) {
        restTemplate.postForObject(url_base+"save",student,null);
    }

    @PutMapping("/update")
    public void update(@RequestBody Student student) {
        restTemplate.put(url_base+"update",student);
    }
    @DeleteMapping("/{id}")
    public void deleteById(@PathVariable("id") long id) {
        restTemplate.delete(url_base+"{id}",id);
    }
}

服务消费者

将restTemplate子项目中添加额eurekaClient依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    <version>2.2.5.RELEASE</version>
</dependency>

添加配置

server:
  port: 8012


spring:
  application:
    name: consumer
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

服务网关

Spring Cloud集成了zuul组件,实现服务网关

  • 什么是zuul?
    zuul是Netflix提供了一个开源的api网关服务器,是客户端和网站后端所有请求的中间层,对外开放的一个api,将所有请求导入统一的入口,屏蔽了服务端的具体实现逻辑,zuul可以实现反向代理的功能,在网关内部实现动态路由,身份认证,ip过滤,数据监控等。

  • 代码

  1. 创建工程,添加pom依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
</dependencies>
  1. 添加配置

server:
  port: 8020
spring:
  application:
    name: gateway
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
zuul:
  routes:
    provider:/p/**

属性说明

zuul.routes.provider: 给服务提供者provider设置映射

  1. 创建启动类
@EnableZuulProxy
@EnableAutoConfiguration
public class ZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication.class,args);
    }
}

注解说明

@EnableZuulProxy:包含了EnableZuulServer,蛇者该类是网管的启动类
@EnableAutoConfiguration:可以帮助Spring Boot应用将所有符合条件的@Configuration配置加载到当前Spring Boot创建并使用的ioc容器中。

  • zuul自带了负载均衡功能
    示例:
    修改provider代码,新增portController
@RestController
@RequestMapping("/port")
public class PortController {
    @Value("${server.port}")
    private  String port;

    @RequestMapping("/")
    public String index(){
        return "当前端口为"+port;
    }
}

新建启动类EurekaClientApplication2

@SpringBootApplication
public class EurekaClientApplication2 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApplication2.class,args);
    }
}

启动第一个启动类
修改端口号为8011
启动第二个启动类
此时已有两个服务
在这里插入图片描述
调用网关如下:
在这里插入图片描述
在这里插入图片描述

Ribbon负载均衡

  • 什么是Ribbon
    Spring Cloud Ribbon 是一个负载均衡解决方案,Ribbon是Netflix发布的负载均衡器,Spring Cloud Ribbon是基于NetFlix Ribbon实现是对于一个http请求进行控制的负载均衡客户端。

在注册中心对Ribbon进行注册之后,Ribbon就可以基于某种负载均衡算法,如 轮训,随机,加权轮训,加权随机等自动帮助服务消费者调用接口,开发者也可以根据具体需求自定义Ribbon负载均衡算法。实际开发中,Spring cloud
ribbon需要结合Spring cloud Eureka 使用,Eureka Server提供所有可以调用的服务提供者列表,Ribbon基于特定的负载均衡算法,从这些服务提供者中选择要调用的具体实例。

  • 使用示例
  1. 创建工程,添加依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    <version>2.2.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-commons</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>

  1. 创建配置文件
server:
  port: 8040
spring:
  application:
    name: ribbon
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
  1. 创建启动类
@SpringBootApplication
public class RibbonApplication {
    public static void main(String[] args) {
        SpringApplication.run(RibbonApplication.class,args);
    }
}
  1. 创建配置类
@Configuration
public class Config {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return  new RestTemplate();
    }
}

@LoadBalanced:声明一个基于Ribbon的负载均衡

5 . 调用

   @GetMapping("/findAll")
    public Collection<Student> findAll() {
//        return restTemplate.getForEntity("http://localhost:8010/student/findAll", Collection.class).getBody();
        return  restTemplate.getForObject("http://provider/student/findAll",Collection.class);
    }

    @GetMapping("/index")
    public String index(){
        return restTemplate.getForObject("http://provider/port/",String.class);
    }

Feign

  • 什么是Feign
    与Ribbon一样,Feign也是由 NetFlix提供的,Feign是一个声明式,模板画的WebService客户端,简化了开发者编写web服务客户端的操作,开发者可以通过简单的接口和注解来调用Http Api,Spring Cloud Feign整合了Ribbon和Hystrix,具有可插拔,基于注解,负载均衡,服务熔断等一系列便捷操作功能。

相比较于Ribbon+RestTemplate的方式,Feign大大简化了代码的开发,Feign支持多种注解,包括Feign注解,JAX_RS注解,Spring Mvc注解等,spring cloud对feign进行了优化,整合了Ribbon和eureka,从而让Feign的使用更加方便。

  • Ribbon和Feign的区别

Ribbon是一个通用的HTTP客户端工具,Feign是基于Ribbon实现。

  • Feign的特点
  1. Feign是一个声明式的WEbService客户端。
  2. 支持Feign注解,Spring mvc注解,jax-rs注解
  3. Feign基于Ribbon实现,使用起来更加简单
  4. Feign集成了Hystrix,具备服务熔断功能
  • 实现

      1. 创建工程,添加依赖
    
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
</dependencies>
  1. 添加配置
server:
  port: 8050


spring:
  application:
    name: feign
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
  1. 创建启动类
@SpringBootApplication
@EnableFeignClients
public class FeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(FeignApplication.class,args);
    }
}
  1. 声明接口
@FeignClient(value = "provider")
public interface FeignProviderClient {
    
    @GetMapping("/student/findAll")
    public Collection<Student> findAll();
    @GetMapping("/port/")
    public String port();
}
  1. 服务熔断
    • 添加配置
#开启熔断器
feign:
  hystrix:
    enabled: true

feign.hystrix.enabled:是否开启熔断器

  • 创建FeignPorviderClient接口的实现类FeignError,定义容错处理逻辑,通过@Conponent注解将FeignError实例注入ioc容器
@Component
public class FeignError implements FeignProviderClient {

    @Override
    public Collection<Student> findAll() {
        return null;
    }

    @Override
    public String port() {
        return "服务器维护中";
    }
}

  • 在FeignProviderClient定义处通过@FeignClient的fallback属性设置映射
@FeignClient(value = "provider" ,fallback = FeignError.class)
  • 使用
    在这里插入图片描述

Hystrix容错机制

在不改变各个微服务调用关系的前提下,针对错误情况进行预先处理。

  • 设计原则
  1. 服务隔离机制
  2. 服务降级机制
  3. 熔断机制
  4. 提供实时的监控和报警功能
  5. 提供实时的配置修改功能

Hystrix数据监控需要结合Spring Cloud Actutor来使用,Actutor提供了对服务的健康,数据统计,可以通过hystrix-stream节点获取监控的请求数据,提供了可视化的监控界面

  • 使用
  1. 创建工程,引入依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
</dependencies>
  1. 创建配置文件
server:
  port: 8060

spring:
  application:
    name: hystrix

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    prefer-ip-address: true
feign:
  hystrix:
    enabled: true
management:
  endpoints:
    web:
      exposure:
        include: 'hystrix.stream'
  1. 创建启动类

@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrixDashboard
public class HystrixApplication {
    public static void main(String[] args) {
        SpringApplication.run(HystrixApplication.class,args);
    }
}

注解说明

@EnableCircuitBreaker:声明启动数据监控
@EnableHystrixDashboard:声明启动可视化的数据监控

Spring Cloud 配置中心

SpringCloud Config,通过服务端可以为多个客户端提供配置服务。Spring Cloud Config可以将配置文件存储在本地,也可以将配置文件存储在远程git仓库,Config Server,,通过他管理所有的配置文件

本地文件配置

  1. 创建工程,添加依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
</dependencies>
  1. 添加配置文件
server:
  port: 8762

spring:
  application:
    name: native-config-server
  profiles:
    active: native
  cloud:
    config:
      server:
        native:
          search-locations: classpath:/shared

说明

profile.active :配置文件的获取方式
cloud.config.server.native.search-locations :本地配置文件存放的路径

  1. resources路径创建shared文件夹,并在此路径下创建configclient.yml
server:
  port: 8080
foo: foo version 1
  1. 创建启动类
@SpringBootApplication
@EnableConfigServer
public class NativeConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(NativeConfigServerApplication.class,args);
    }
}

@EnableConfigServer: 声明配置中心

创建客户端读取本地配置中心的配置文件

  1. 创建工程,添加依赖
<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
    </dependencies>
  1. 创建bootstrap.yml,配置读取本地配置中心的相关信息
spring:
  application:
    name: configclient
  profiles:
    active: dev
  cloud:
    config:
      uri: http://localhost:8762
      fail-fast: true

说明

cloud.config.uri :本地Config Server的访问路径
cloud.config.fial-fase : 设置客户端优先判断Config Server获取是否正常
通过spring.application.name+spring.profiles.active拼接目标配置文件名 ,Config Server中查找改文件
在这里插入图片描述
3. 创建启动类

@SpringBootApplication
public class NativeConfigClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(NativeConfigClientApplication.class,args);
    }
}

  1. 创建Controller
@RestController
@RequestMapping("/native")
public class NativeConfigController {
    @Value("${server.port}")
    private String port;
    @Value("${foo}")
    private String foo;
    @RequestMapping("/index")
    public String index(){
        return  this.port+"-"+this.foo;
    }
}

远程配置

  1. 创建配置文件 上传GitHub
server:
  port: 8070
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8760/eureka
spring:
  application:
    name: configclient
  1. 创建ConfigServer,添加依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
</dependencies>
  1. 创建配置文件application.yml
server:
  port: 8888
spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/YouZhiMing-Git/springcloud-learn.git
          search-paths: config
          username: *****
          password: *****
      label: master
eureka:
  client:
    service-url:
      defaultZone: localhost:8761/eureka

  1. 创建启动类
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class,args);
    }
}

创建客户端Config Client

  1. 创建工程,引入依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-netflix-eureka-client</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
        <version>2.2.5.RELEASE</version>
    </dependency>
</dependencies>
  1. 创建bootstrap.yml
spring:
  cloud:
    config:
      name: configclient
      label: master
      discovery:
        enabled: true
        ##注册中心中的名字
        service-id: config-server

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  1. 创建启动类
@SpringBootApplication
public class ConfigClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigClientApplication.class,args);
    }
}

服务跟踪

SpringCloud Zipkin
zipkin是一个可以采集并且跟踪分布式系统中请求数据的组件,让开发者可以更加直观的监控到请求在各个微服务所耗费的时间等,zipkin:zipkin server ,zipkin client

创建服务端

  1. 创建工程,添加依赖
<dependencies>
    <!--服务端-->
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-server</artifactId>
        <version>2.12.9</version>
    </dependency>
    <!--图形界面展示-->
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-autoconfigure-ui</artifactId>
        <version>2.12.9</version>
    </dependency>
</dependencies>
  1. 创建配置文件
server:
  port: 9090
  1. 添加启动类
@SpringBootApplication
@EnableZipkinServer
public class ZipkinApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZipkinApplication.class,args);
    }
}

创建客户端

创建工程,添加依赖

 <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
    <version>2.2.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-netflix-eureka-client</artifactId>
</dependency>

添加配置文件

server:
  port: 8900
spring:
  application:
    name: zipkin-client
  sleuth:
    web:
      client:
        enabled: true
    sampler:
      probability: 1.0
  zipkin:
    base-url: http://localhost:9090/
eureka:
  client:
    service-url:
      deafaultZone: http://localhost:8761/eureka/

属性说明

spring.sleuth. web.client.enabled :设置开启请求跟踪
spring.sleuth. sampler.probability :设置采样比例,默认1.0
spring.zipkin. base-url:zipkin Server的地址

创建启动类

@SpringBootApplication
public class ZipkinClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZipkinClientApplication.class,args);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值