【博学谷学习记录】超强总结,用心分享|【服务框架基础】SpringCloud

目录

1.springCloud概要

1.1 springCloud说明

1.2 springCloud特点

2.服务注册与发现

2.1 服务发现组件功能

2.2 服务发现方式

2.3 创建服务注册中心(spring-cloud-eureka-server)

2.3.1 pom.xml

2.3.2 application.yml

2.3.3 在启动类添加@EnableEurekaServer注解

2.4 创建服务提供者(spring-cloud-eureka-provider)

2.4.1 pom.xml

2.4.2 application.yml

2.4.3 启动类添加@EnableEurekaClient,指明是一个Eureka Client

3.服务消费者

3.1 Ribbon基本用法

3.1.1 在服务提供者(spring-cloud-eureka-provider)新增一个IndexController作为服务提供接口

3.1.2 创建一个服务消费者(spring-cloud-eureka-consumer-ribbon)

3.2 Ribbon负载均衡策略

3.2.1 对单一服务指定特定负载均衡策略

3.2.2 对所有服务指定特定负载均衡策略

3.3 配置文件自定义Ribbon客户端

3.4 Feign基本用法

4.断路器:Hystrix(spring-cloud-eureka-consumer-hystrix)

4.1 Hystrix使用

4.1.1 ribbon使用hystrix

4.1.2 断路器仪表盘

4.1.3 feign集成Hystrix

5.路由器和过滤器(Zuul)

5.1 Zuul概要

5.1.1 zuul创建(spring-cloud-eureka-zuul)

5.1.2 服务过滤

6.文件配置

6.1 创建文件配置服务端(spring-cloud-eureka-config-server)

6.2 创建配置文件服务器客户端(spring-cloud-eureka-config-client)

6.3 利用Eureka实现高可用服务配置中心

7.消息总线(spring cloud bus)

7.1 spring cloud bus概述

7.2 通过配置kafka实现消息总线服务(spring-cloud-eureka-config-client)

7.2.1 config-server连接到kafka服务器

7.2.2 config-client连接kafka服务器


1.springCloud概要

1.1 springCloud说明

Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具,例如配置管理,服务发现,断路器,智能路由,微代理,控制总线。

1.2 springCloud特点

  • 约定优于配置
  • 开箱即用,快速启动
  • 使用环境广泛,如pcServer/docker/云等
  • 轻量级组件,组件支持丰富齐全
  • 多种选型,如zk/Eureka等
  • 负载均衡
  • 断路器
  • 分布式消息传递

2.服务注册与发现

2.1 服务发现组件功能

  • 服务注册表:记录当前可用服务实例网络信息的数据库,是服务发现的核心机制
  • 服务注册:服务消费者和服务提供者通过心跳机制注册到服务注册中心(springCloud推荐使用Eureka创建服务注册中心)
  • 健康检查:服务发现组件长时间接收不到心跳便会删除该服务的注册信息,对外不在提供该服务的ip和端口

2.2 服务发现方式

  • 客户端Eureka或zk
  • 服务端Consul+nginx

2.3 创建服务注册中心(spring-cloud-eureka-server)

eureka是一个高可用的服务发现组件,无后端缓存;

eureka是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的;

eureka集成在spring-cloud-netflix项目中,以实现Spring Cloud的服务发现功能;

默认情况eureka server就是一个eureka client,需要指定一个server;

eureka.client.register-with-eureka:false和fetch-registry:false指明该服务是一个eureka server;

2.3.1 pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>

2.3.2 application.yml

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka

2.3.3 在启动类添加@EnableEurekaServer注解

@SpringBootApplication
@EnableEurekaServer
public class SpringCloudEurekaServerApplication {

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

访问http://localhost:8081进入eureka server界面

2.4 创建服务提供者(spring-cloud-eureka-provider)

2.4.1 pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

2.4.2 application.yml

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8081/eureka/
server:
  port: 8082
spring:
  application:
    name: eureka-provider

2.4.3 启动类添加@EnableEurekaClient,指明是一个Eureka Client

@SpringBootApplication
@EnableEurekaClient
public class SpringCloudEurekaProviderApplication {

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

3.服务消费者

3.1 Ribbon基本用法

ribbon是负责客户端负载均衡

ribbon可以通过在客户端经过一系列算法来均衡调用服务,Ribbon工作是分为两步:

第一步:优先选择在同一个Zone且负载较少的eureka server

第二步:根据用户指定的策略,从Server取到的服务注册列表中选择一个地址,Ribbon提供了包括轮询/随机/根据响应时间加权等多种策略

3.1.1 在服务提供者(spring-cloud-eureka-provider)新增一个IndexController作为服务提供接口

/**
* com.spring.cloud.eureka.ribbon.controller.IndexController
*/
@RestController
public class IndexController {

    @RequestMapping(value = "/ribbon")
    public String ribbon(String name) {
        return "hello "  + name + ", welcome to ribbon world! ";
    }

}

3.1.2 创建一个服务消费者(spring-cloud-eureka-consumer-ribbon)

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

application.yml

server:
  port: 8083
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8081/eureka/
spring:
  application:
    name: eureka-ribbon

在启动类中添加@EnableDiscoveryClient向服务注册中心注册,并向程序的IOC注入一个RestTemplate,添加@LoadBalanced 注解表明restTemplate开启负载均衡功能。

@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudEurekaConsumerApplication {

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

	@Bean
	@LoadBalanced
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
}

创建一个Service请求服务提供者提供的接口

/**
* com.spring.cloud.eureka.ribbon.service.IndexService
*/
@Service
public class IndexService {
    private static final String PATH = "http://EUREKA-PROVIDER/ribbon";
    @Autowired
    private RestTemplate restTemplate;
    public String hello(String name) {
        //该处做负载均衡
        return restTemplate.getForObject(PATH + "?name=" + name, String.class);
    }
}

3.2 Ribbon负载均衡策略

  • 轮询负载均衡策略:按照i=(i+1)%n的轮询调度策略调用第i台服务器
  • 随机加载负载均衡策略
  • 加权响应时间负载均衡:根据响应时间分配一个weight;响应时间越长,weight越小,选中概率越低
  • 区域感知轮询负载均衡

3.2.1 对单一服务指定特定负载均衡策略

@RibbonClient(name = "eureka-provider", configuration = FooConfiguration.class)

com.spring.cloud.eureka.ribbon.config.TestConfiguration

@Configuration
@RibbonClient(name = "eureka-provider", configuration = FooConfiguration.class)
public class TestConfiguration {
}

com.spring.cloud.config.ribbon.FooConfiguration

@Configuration
public class FooConfiguration {

    @Bean
    public IRule ribbonRule(IClientConfig config) {
//        return new BestAvailableRule(); //最小的并发请求的server
//        return new WeightedResponseTimeRule(); //加权响应时间负载均衡
//        return new RetryRule(); //在选定的负载均衡策略机上重试机制
//        return new RoundRobinRule(); //roundRobin方式轮询
//        return new ZoneAvoidanceRule(); //区域感知轮询负载均衡
        return new RandomRule();//随机加载
    }
}

注:FooConfiguration类不应该在主应用程序可以扫描(@ComponentScan)到包及其子包中,否则该配置类被所有的@RibbonClients共享;

3.2.2 对所有服务指定特定负载均衡策略

@RibbonClients(defaultConfiguration = {FooConfiguration.class})
public class SpringCloudEurekaConsumerApplication {

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

	@Bean
	@LoadBalanced
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
}

3.3 配置文件自定义Ribbon客户端

配置文件配置格式:clientName.ribbon.前缀

  • NFLoadBalancerClassName:配置com.netflix.loadbalancer.ILoadBalancer接口的实现
  • NFLoadBalancerRuleClassName:配置com.netflix.loadbalancer.IRule接口的实现
  • NFLoadBalancerPingClassName:配置com.netflix.loadbalancer.IPing接口的实现
  • NIWSServerListClassName:配置com.netflix.loadbalancer.ServerList接口的实现
  • NIWSServerListFilterClassName:配置com.netflix.loadbalancer.ServerListFilter接口的实现

application.yml配置

eureka-provider:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

3.4 Feign基本用法

声明式web服务客户端,具有可插入注释支持(包括Feign注释和JAX-RS注释); 支持可插拔编码器和解码器 默认集成ribbon和eureka,实现负载均衡

feign服务创建

  • pom.xml添加配置

      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-feign</artifactId>
      </dependency>
    
  • application.yml添加配置

      server:
        port: 8085
      spring:
        application:
          name: eureka-feign
      eureka:
        client:
          service-url:
            defaultZone: http://localhost:8081/eureka/
    
  • 启动类增加@EnableFeignClients注解开启Feign功能

      @SpringBootApplication
      @EnableEurekaClient
      @EnableFeignClients
      public class SpringCloudEurekaConsumerFeignApplication {
    
          public static void main(String[] args) {
              SpringApplication.run(SpringCloudEurekaConsumerFeignApplication.class, args);
          }
      }
    
  • 创建一个接口调用服务接口,通过添加@FeignClient("serviceName")注解来指定调用哪个服务

      @FeignClient(value = "EUREKA-PROVIDER")
      public interface FeignService {
    
          @RequestMapping(value = "/feign", method = RequestMethod.GET)
          String feign(@RequestParam(value = "name") String name);
      }
    

4.断路器:Hystrix(spring-cloud-eureka-consumer-hystrix)

如果底层服务出现故障有可能会导致整个服务的连锁故障,当对特定的服务调用不可用达到一个阀值(Hystric是5秒20次)断路器将会被打开,从而避免连锁反应。

4.1 Hystrix使用

4.1.1 ribbon使用hystrix

  • pom.xml

    org.springframework.cloud spring-cloud-starter-hystrix
  • 启动类添加@EnableHystrix注解开启Hystrix

    @SpringBootApplication @EnableEurekaClient @EnableHystrix public class SpringCloudEurekaConsumerHystrixApplication {

      public static void main(String[] args) {
      	SpringApplication.run(SpringCloudEurekaConsumerHystrixApplication.class, args);
      }
    
      @Bean
      @LoadBalanced
      public RestTemplate restTemplate() {
      	return new RestTemplate();
      }
    

    }

  • 在service类中添加@HystrixCommand(fallbackMethod = "fallback")创建熔断器功能并指定了熔断返回的内容

    @Service public class HystrixRibbonService {

      @Autowired
      private RestTemplate restTemplate;
    
      @HystrixCommand(fallbackMethod = "fallback")
      public String index(String name) {
          return restTemplate.getForObject("http://EUREKA-PROVIDER/ribbon?name=" + name, String.class);
      }
    
      public String fallback(String name) {
          return "sorry, " + name + " system request error!";
      }
    

    }

4.1.2 断路器仪表盘

Hystrix的主要优点之一是它收集关于每个HystrixCommand的一套指标, Hystrix仪表板以有效的方式显示每个断路器的运行状况.

当使用Ribbon客户端的Hystrix命令时需要确保Hystrix超时配置长于Ribbon的超时配置, 包括可能进行的任何潜在的重试. 例如: 如果Ribbon连接超时为一秒钟, 并且Ribbon客户端可能会重试该请求三次, 这时Hystrix超时需要略超过三秒钟。

  • 集成断路器仪表盘

pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>

在启动类中添加加@EnableHystrixDashboard

@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
@EnableHystrixDashboard
public class SpringCloudEurekaConsumerHystrixApplication {

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

	@Bean
	@LoadBalanced
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}
}

访问http://ip:port/hystrix访问仪表盘界面, 并将仪表板指向Hystrix客户端应用程序中的单个实例/hystrix.stream端点.

4.1.3 feign集成Hystrix

启动类添加@EnableFeignClients注解

@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
@EnableHystrixDashboard
@EnableFeignClients
public class SpringCloudEurekaConsumerHystrixApplication {

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

	@Bean
	@LoadBalanced
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}
}

application.yml增加feign.hystrix.enabled=true表示打开断路器

feign:
  hystrix:
    enabled: true

service:fallback指定断路器返回的异常信息类

@FeignClient(value = "EUREKA-PROVIDER", fallback = HystrixFeignServiceError.class)
public interface HystrixFeignService {

    @RequestMapping(value = "/feign", method = RequestMethod.GET)
    String feign(@RequestParam(value = "name") String name);
}

异常信息类需要实现service类并且注入ioc容器类

@Component
public class HystrixFeignServiceError implements HystrixFeignService {
    @Override
    public String feign(String name) {
        return "sorry " + name + ", system error!";
    }
}

5.路由器和过滤器(Zuul)

5.1 Zuul概要

Zuul是Netflix的基于JVM的路由器和服务器端负载均衡器,主要功能是用于路由转发和过滤器;

Zuul的作用:

  • 认证
  • 洞察
  • 压力测试
  • 金丝雀测试
  • 动态路由
  • 服务迁移
  • 负载脱落
  • 安全
  • 静态响应处理
  • 主动/主动流量管理

5.1.1 zuul创建(spring-cloud-eureka-zuul)

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

启动类添加@EnableZuulProxy注解开启zuul功能

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class SpringCloudEurekaZuulApplication {

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

application.yml

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8081/eureka/
server:
  port: 9091
spring:
  application:
    name: eureka-zuul
zuul:
  routes:
    feign-url:
      path: /feign-url/**
      serviceId: eureka-feign
    ribbon-url:
      path: /ribbon-url/**
      serviceId: eureka-ribbon

说明:/feign-url开头的请求转发到eureka-feign服务,/ribbon-url开头的请求转发到eureka-ribbon服务

5.1.2 服务过滤

zuul可以做服务过滤,做一下安全验证。

代码示例:

@Component
public class IndexFilter extends ZuulFilter {
    /**
     * filterType返回一个字符串代表过滤器的类型,返回的字符串及表示的含义如下:
     * pre:在请求被路由之前调用
     * route:在请求被路由之时调用
     * post:在请求被路由之后被调用
     * error:处理请求发送错误时被调用
     *
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 定义过滤器的执行顺序,数值越大优先级越低
     *
     * @return
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 判断过滤器是否要过滤,true表示过滤器总是生效(这里可以进行相应的逻辑判断过滤器是否生效)
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 过滤器具体的逻辑实现
     *
     * @return
     */
    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();

        String name = request.getParameter("name");

        System.out.println("[IndexFilter] >>> name = " + name);

        if ("jack".equals(name)) {
            context.setResponseStatusCode(200);
            context.setSendZuulResponse(true);//true表示对该请求进行路由,false表示过滤该请求,不进行路由
            context.set("isSuccess", true);//告诉下一个Filter上一个Filter的状态
        } else {
            context.setSendZuulResponse(false);
            context.setResponseStatusCode(1001);
            context.setResponseBody("name is error! name = " + name);//返回错误的内容
            context.set("isSuccess", false);
        }

        return null;
    }
}

6.文件配置

6.1 创建文件配置服务端(spring-cloud-eureka-config-server)

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

application.yml

spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/chasdream/spring-cloud-config.git
          search-paths: spring-cloud-config
      label: master
server:
  port: 7060

启动类增加@EnableConfigServer, 开启配置服务器功能

@SpringBootApplication
@EnableConfigServer
public class SpringCloudEurekaConfigServerApplication {

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

注: application.yml文件配置说明:

spring.cloud.config.server.git.uri 配置git仓库地址
spring.cloud.config.server.git.search-paths 配置仓库路径
spring.cloud.config.label 配置仓库分支
spring.cloud.config.server.git.username 配置git仓库用户名(公有仓库可省略)
spring.cloud.config.server.git.password 配置git仓库用户密码(公有仓库可省略)

启动服务 

{
    "name":"config-server",
    "profiles":[
        "dev"
    ],
    "label":"master",
    "version":"2bd741fa42e2a7bb70a5816f8ddef3796c11737a",
    "state":null,
    "propertySources":[
        {
            "name":"https://github.com/chasdream/spring-cloud-config.git/application-dev.properties",
            "source":{
                "name":"chasdream-dev"
            }
        }
    ]
}

6.2 创建配置文件服务器客户端(spring-cloud-eureka-config-client)

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

bootstrap.yml

spring:
  application:
    name: config-client
  cloud:
    config:
      label: master
      profile: dev
      uri: http://localhost:7060/
server:
  port: 7061

注:文件配置客户端配置文件名必须是bootstrap命名,不能是application命名;

bootstrap.yml配置文件说明:

spring.cloud.config.label 配置远程仓库分支
spring.cloud.config.profile 配置选择环境的配置文件
spring.cloud.config.uri 配置服务中心的地址

6.3 利用Eureka实现高可用服务配置中心

配置文件服务端及客户端pom.xml文件增加Eureka

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

配置文件服务器application.yml配置文件修改

spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/chasdream/spring-cloud-config.git
          search-paths: spring-cloud-config
      label: master
server:
  port: 7060
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8081/eureka/

配置文件客户端bootstrap.yml配置文件修改

spring:
  application:
    name: config-client
  cloud:
    config:
      label: master
      profile: dev
      discovery:
        service-id: config-server 文件配置中心服务名,用于替换uri
        enabled: true  表示从配置中心读取文件
      #uri: http://localhost:7060/ 用service-id替换
server:
  port: 7061
eureka:
    client:
      service-url:
        defaultZone: http://localhost:8081/eureka/

7.消息总线(spring cloud bus)

7.1 spring cloud bus概述

  • Spring Cloud Bus将分布式系统的节点与轻量级消息代理链接,可以用于广播配置文件的更改或其他管理指令,也可用于监控和应用程序之间的通信通道;
  • Spring Cloud Bus唯一的实现是通过使用AMQP代理作为传输,默认支持rabbitmq和kafka

7.2 通过配置kafka实现消息总线服务(spring-cloud-eureka-config-client)

7.2.1 config-server连接到kafka服务器

配置文件服务端pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>

配置文件服务端application.yml

spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/chasdream/spring-cloud-config.git
          search-paths: spring-cloud-config
      label: master
    stream:
      kafka:
        binder:
          brokers: 127.0.0.1:9092
          zk-nodes: 127.0.0.1:2181
server:
  port: 7060
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8081/eureka/

注:

  • spring.cloud.stream.kafka.binder.brokers 配置kafka服务列表
  • spring.cloud.stream.kafka.binder.defaultBrokerPort 配置kafka服务默认端口,如果brokers没有配置端口这使用默认值9092
  • spring.cloud.stream.kafka.binder.zk-nodes 配置zk节点列表
  • spring.cloud.stream.kafka.binder.defaultZkPort 配置zk节点默认端口,如果zk-nodes没有配置端口这使用默认值2181

7.2.2 config-client连接kafka服务器

配置文件客户端pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>

配置文件客户端bootstrap.yml

spring:
  application:
    name: config-client
  cloud:
    config:
      label: master
      profile: dev
      discovery:
        service-id: config-server
        enabled: true
      #uri: http://localhost:7060/
    stream:
      kafka:
        binder:
          brokers: 127.0.0.1:9092
          zk-nodes: 127.0.0.1:2181
server:
  port: 7061
eureka:
    client:
      service-url:
        defaultZone: http://localhost:8081/eureka/
management:
  security:
    enabled: false

注:

  • management.security.enabled false:禁用安全管理策略
  • @RefreshScope 允许动态刷新配置
  • 文件配置客户端发post请求http://localhost:7061/bus/refresh 重新读取git配置文件信息

@RefreshScope示例:

@Controller
@RefreshScope
public class ConfigController {

    @Value("${name}")
    public String name;

    @ResponseBody
    @RequestMapping(value = "/config")
    public String config() {
        return name;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值