微服务技术

微服务技术

微服务和spring cloud
微服务是分布式架构的一种,spring cloud解决了分布式的分步治理问题

微服务是哪些

  1. 拆分
    1. 将服务拆分成块,拆分的越多就越复杂
  2. 注册中心
    1. 所有的东西从注册中心找
  3. 配置中心
    1. 配置的变更,会通知所有的模块,热更新
  4. 网关中心
    1. 客户的权限是否通过
    2. 可以将客户请求路由到具体模块
  5. 数据库
  6. 缓存
    1. 数据库的数据放内存,解决并发
  7. 海量搜索
    1. 分布式搜索
  8. 异步通信消息队列
    1. 业务的跨服务,调用时长长,性能下降
    2. 服务a通知服务b、c,服务a直接结束,这样解决并发,异步解决
  9. 异常定位
    1. 分布式日志服务,统计所有的日志
    2. 监控和链路追踪,检测所有的状态,栈信息
  10. 自动化部署
    1. Jenkins自动化
    2. Docker镜像
    3. Kubernets Rancher实现自动化部署

技术栈学习过程

  1. 实用篇 7天
  2. 高级篇 5天
  3. 面试篇 2天

实现黑马旅游项目

DAY ONE 微服务框架

认识微服务

微服务架构演变

  1. 单体架构:业务都是一个项目中开发,打包成一个部署
    1. 架构简单
    2. 部署成本低
    3. 耦合度高
  2. 分布式架构
    1. 根据业务功能拆分功能
    2. 降低耦合,利于服务的拓展
    3. 部署复杂,拆分过程服务治理复杂
    4. 远程调用 RPC
    5. 服务健康如何感知
  3. 微服务方案
    1. 经过良好架构设计的分布式架构
    2. 单一职责,粒度小,每一个服务对应唯一的业务能力,单一职责,避免重复开发
    3. 面向服务,微服务对外暴露接口,远程调用接口,接口标准统一
    4. 自治,团队独立,技术独立,数据独立,部署独立
    5. 隔离性,服务要做好隔离,容错,降级等,避免一个宕机影响别人宕机
    6. 目的:高内聚,低耦合

微服务架构

国内就是spring cloud 和阿里的Dubbo

DubboSpring CloudSpring Cloud Alibaba
注册中心zookeeper、redisEureka、ConsulNacos、Eureka
远程调用服务Dubbo协议Feign(基于http协议)Dubbo、Feign
配置中心SpringCloudConfigSpringCloudConfig、Nacos
服务网关SpringCloudGateWay、ZuulSpringCloudGateWay、Zuul
服务监控和保护dubbo-admin,功能比较弱HystrixSentinel

企业需求

  1. SpringCloud+Feign
    1. 接口是resful
    2. 调用Feign
  2. SpringCloudAlibaba+Feign
    1. 接口resful
    2. 调用Feign
  3. SpringCloudAlibaba+Dubbo
    1. 接口Dubbo
    2. 调用Dubbo
  4. Dubbo原始(比较少)
    1. 接口Dubbo
    2. 调用Dubbo

springcloud

是国内最广泛的微服务框架,基本都是所有公司的开源框架整合的。

spring cloud中的最重要的东西就是spring boot,就是自动装配的过程,原生的用起来很麻烦

版本对应

版本有对应,比如 Hoxton.SR10对应Spring boot 2.3.x

分布式服务架构案例

服务拆分

  1. 不同的微服务,不能重复开发相同业务
  2. 微服务的数据独立,每个微服务都有自己的数据库,不要访问其他微服务的数据库,去耦合
  3. 微服务需要将自己的部分业务暴露为接口,供其他业务使用

案例

  1. 根据业务模块进行拆分,不要重复开发
  2. 业务暴露
  3. 独立数据库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XBMiObfz-1683281154805)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502163000012.png)]

微服务远程调用

需求:查询订单的时候,把所属的用户信息一起返回


  1. 目前情况

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OVQhaaS1-1683281154806)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502163116137.png)]

user信息目前是null,无法查询到用户信息

  1. 需求实现

订单的情况向用户的进行远程调用

目前用户端暴露了一个restFul接口,/user/id,订单模块应该发送一个http请求,将返回的结果拿到

Spring有一个RestTemplate,就是用来发送http请求的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-94VgQ9OQ-1683281154806)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502163812120.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7HkVMsYA-1683281154806)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502164357937.png)]

结果有了,可以看到

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Awate9Ff-1683281154807)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502164414484.png)]

消费者和提供者

从前面可以看到,order调用了user的http接口,所以在这个案例中,order是消费者,user是提供者


如果服务a调用了服务b,服务b调用了服务c,那么服务b是什么角色?

这个时候是相对的,需要根据具体的业务,所以服务b在这里既可以是提供者也可以是消费者

eureka注册

远程服务调用出现的问题

  1. 之前是将url硬编码在实际代码中,但是这个时候具体的url会变化,比如开发环境和测试环境不同,集群开发也不同,所以在这个时候,需要将url分成实际情况,不能硬编码在代码中,eureka就是用来解决的

eureka的作用
  1. 注册中心。
    1. 每一个服务启动的时候会在注册中心中进行注册,注册有端口,url等,因为每一个都可以是提供者
    2. 消费者需要消费,找注册中心要
    3. 消费者具体的情况,哪一个到底是可以的,注册中心30s发送一次心跳,不发送的就会被踢掉
  2. 解决方法
    1. 消费者如何获取提供者的具体信息
      1. 提供者的所有信息都在注册中心中,eureka保留保管这些信息,消费者直接找eureka要
    2. 多个提供者如何选取
      1. 负载均衡的概念,使用相关算法
    3. 如何保证提供者的健康状态
      1. 30s的心跳发送,保证提供者都是活着的
      2. 不发送心跳的会被踢出
      3. 消费者每次拉取可以有最新信息
  3. 总体:
    1. 注册中心,管理所有信息
    2. 客户端:分为提供者和消费者,都有可能是提供者和消费者,所以大家都是相对而言

动手实践

搭建eureka注册中心

创建一个新的项目,引入一个依赖,eureka-server的starter,也就是spring引入的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v1dW5ShH-1683281154807)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502210539802.png)]

这里不需要版本,因为父工程已经将所有的版本信息写好了


之后创建一个注解,也就是eureka的开关

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ytqaNvuZ-1683281154808)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502210837417.png)]


之后编写yml文件,也就是eureka的配置信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VYcoswoz-1683281154808)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502211506336.png)]


之后可以在浏览器中找到对应的实例列表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lEFgOvGk-1683281154809)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502211458091.png)]

这里可以看到目前就是我注册了我自己,所以只有一个

服务注册
  1. 在需要加入的微服务中加入依赖,依赖不一样,之前是注册中心,也就是服务端,现在是client端,客户端

    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4zHBbINM-1683281154809)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502211905599.png)]
  2. 在yml文件中配置信息

    1. 直接cv[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mBzY04Tl-1683281154810)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502212213954.png)]
    2. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4hzvzoPB-1683281154810)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502212244004.png)]

order-service同理


意外弄了两个,现在看看能不能删除一个

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RdwXmUb5-1683281154810)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502212647772.png)]


重启eureka-server就可以了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WsWnWI1y-1683281154811)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502212933358.png)]


启动多个实例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-596Eo9hh-1683281154812)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502213235432.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r1dbkTpg-1683281154812)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502213543386.png)]

之后成功,就有两个了,这就是实例的列表了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IbvwRGEu-1683281154813)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230502213741382.png)]

服务发现

希望可以通过order-service完成对于两个user-service的负载均衡的服务拉取

  1. 修改order-service的代码,将路径改为服务名

    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hctL1Pm1-1683281154813)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230503141843240.png)]不再是ip地址了
  2. 将RestTemplate进行负载均衡@LoadBalance

    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HZjTZAmx-1683281154813)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230503141916619.png)]

      直接进行一个负载均衡

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vk4J8e6c-1683281154813)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230503142329849.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fe7tLxuA-1683281154814)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230503142315316.png)]

实现了负载均衡,查询了两次,是不同的userservice

说明不需要管理服务的地址,只需要从服务列表中找到服务的名字,然后交给注册中心就行

这个是通过Ribbon组件实现的

Ribbon负载均衡

流程:

  1. order-service通过http://userservice/user/1这样的访问的,但是这个域名无法直接访问,所以这个是交给Ribbon管理的
  2. Ribbon通过eureka-server得到响应的user-service的真实域名
  3. 通过负载均衡策略,找到真实的地址,要不是8081端口要不是8082端口

负载均衡原理

  1. 通过RibbonLoadBalancerClient是按拦截所有的请求,这个需要拦截的就是@LoadBalance这个注解带来的
  2. 获取Url中的服务id,这个服务id是给定的在Eureka中注册的那个名字
  3. 交给DynamicServerListLoadBalancer,这个从Eureka中拉取叫这个服务id的所有微服务,获取到了服务列表
  4. 通过负载均衡策略,也就是IRule这个接口,按照对应的负载均衡的策略,实现负载均衡。
  5. 将服务列表中的ip地址替换,访问微服务。

负载均衡策略

内置负载均衡规则类规则描述
RoundRobinRule简单的轮询服务器进行负载均衡,是Ribbon默认的负载均衡规则
AvailabilityFilteringRule对于服务器进行过滤和筛选,如果服务器多次链接不上,那么就会判断为短路,会被筛掉。如果服务器的并发过高,也会将其忽略,并发数量可以进行设置。
WeightedResponseTimeRule对于服务器进行权重衡量比较,如果服务器的响应时间过长,那么给与的权重就会比较小,那么后期选择到这个服务器的概率也就会比较小。
ZoneAvoidanceRule以区域可用的服务器为基础进行服务器的选择,首先对于服务器进行区域的选择,之后在这个区域内进行轮询。区域可以理解为一个机房,一个服务站点等。
BestAvailableRule忽略短路的,并且选择并发数较低的。
RandomRule随机选择一个服务器
RetryRule重试机制的选择逻辑

调整负载均衡策略

通过定义IRule可以修改负载均衡策略。

  1. 代码中,在order-service的OrderApplication中定义一个新的IRule

    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-94yiOARH-1683281154814)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230503144845810.png)]

      修改为了随机

      Order-service中的就是全局的,也就是无论你在order-service中调用哪一个微服务,都是采用随机的方式

  2. 基于application.yml文件,新增新的配置

    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h3a2DPgN-1683281154814)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505124900577.png)]

      这个可以指定某一个微服务的负载均衡原则

懒加载

第一次启动

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zc7iE4kX-1683281154814)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505125143090.png)]

第二次启动

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g0xep4OU-1683281154815)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505125132301.png)]

可以看出时间的响应差距很大,说明这个是通过懒加载的方式进行的


第一次加载之后,看日志可以看出,第一次访问的时候会发现服务列表是空的,这个时候因为负载均衡的loadBanlancer还没有加载出来

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SLEyfefF-1683281154815)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505125409363.png)]

之后才有初始化,然后拉取服务列表,发现有两个,懒加载完成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y93B63yK-1683281154815)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505125531371.png)]

之后就缓存在内存中了,这个就是第二次为什么那么快的原因。


如果想要修改的方法,那么就需要在yml文件中进行配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u2R5Fr67-1683281154815)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505125743563.png)]

nacos注册中心

认识和安装nacos

nacos是阿里的产品,现在也是springcloud的一个组件,比eureka更多,国内受欢迎情况好

下载安装之后,使用命令打开

  1. 进入bin目录
  2. startup.cmd -m standalone 表示使用单机模式打开nacos
  3. 访问 http://10.133.181.243:8848/nacos/index.html就可以进入,默认账号密码都是:nacos

nacos入门

服务注册到nacos
  1. 在父工程中引入sppring-cloud-alibaba的管理依赖,这样以后所有的需要使用的依赖版本问题就得到了解决

    1. <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-alibaba-dependencies</artifactId>
          <version>2.2.5.RELEASE</version>
          <type>pom</type>
          <scope>import</scope>
      </dependency>
      
  2. 注释掉之前的eureka的依赖

  3. 添加新的nacos的依赖

    1. <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
      </dependency>
      
  4. 修改user-serivce和order-service的yml文件,注释掉原本eureka的地址,修改为nacos的地址

    1. 是spring的一个配置

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nfOVcyVP-1683281154816)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505131825405.png)]

  5. 启动测试

nacos服务分级存储模型

将一个服务的多个实例放到多个机房,将鸡蛋分在不同的篮子里。

一个机房中的所有实例就称为一个集群。

服务调用的时候尽可能的去访问本地集群,这个也是之前的负载均衡的默认的方法。

配置服务的集群属性
  1. 修改yml文件,增加集群属性
    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hqrZ3nvT-1683281154816)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505134127986.png)]
    2. 修改不同的在不同的集群
  2. 在nacos控制台看到集群属性变化
    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bnRE7eN3-1683281154816)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505134337630.png)]

服务分级模型,就是增加了中间的一层的集群的概念

nacos环境隔离

环境隔离的意思就是能够将本地集群内的访问优先级提高,这样就会优先访问本集群内的东西。

所以修改order-service的集群,放到HZ集群即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dWbe6RJK-1683281154816)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505143915481.png)]

之后修改负载均衡的规则,修改为

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule

这个时候可以看到大概是集群内的随机

如果集群内没有的话,那么就会出现跨集群的访问,这个时候order会有一个警告。


环境隔离

-namespace 就是对于不同环境的服务进行隔离

就是多了一个层的概念,比如开发环境、测试环境等,这就又有了一个隔离的概念

  1. nacos控制台新增一个命名空间
    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Irjx4rqX-1683281154817)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505145417387.png)]
    2. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7IEFkDog-1683281154817)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505145451286.png)]
  2. 代码yml文件配置命名空间
    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zUqSq7wR-1683281154817)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505145528551.png)]
  3. 测试
    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XXh3ysVP-1683281154818)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505145619514.png)]
  4. 刷新浏览器,报错
    1. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FxJS7kXQ-1683281154818)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505145716207.png)]

nacos根据权重负载均衡

nacos默认的时候集群内的随机访问,不会区分

nacos可以修改权重,权重越大,访问的频率就越高

在nacos控制台可以控制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AF2BaH1V-1683281154818)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505144705605.png)]

修改权重

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LMcrqOvL-1683281154818)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505144721352.png)]

这样就会大幅度修改访问频率

权重如果是0,那么就不会被访问了。

修改成0的作用,就是可以将他的权重修改为0,这样就不会访问到,然后就可以升级这个服务,这样就没事了,这就是不停服更新的概念

nacos和eureka的对比

  1. 所有的注册中心都是注册所有的服务提供者,然后消费者都是拉取列表

  2. 每次拉取是懒加载,第一次拉取才会读取,之后使用内存的,所以需要有一个定时拉取的概念,防止内存信息没有更新

  3. 二者差距在服务提供者的健康状态。nacos有临时实例和非临时实例。默认nacos所有的都是临时实例

    1. 临时实例,nacos使用心跳检测,每隔一段时间发送心跳进行健康检测
    2. 非临时实例,nacos不做心跳,nacos主动发送请求,问你还活着不,用来健康检测。如果没有回复,不会踢掉,会保留,等恢复。
  4. 消费者的也会有差距

    1. eureka拉取列表的时候并不知道健康状态,因为是心跳检测,可能不及时
    2. nacos消费者会定时拉取,同时如果列表变化,那么nacos注册中心会主动发送信息,告知消费者列表变化,更加及时。
  5. 修改是否是临时实例

    1.   cloud:
          nacos:
            server-addr: localhost:8848
            discovery:
              cluster-name: HZ
              namespace: bec1d56c-b966-4c23-9641-4a70d1cc5530
              ephemeral: false # 非临时实例
      
    2. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xg39Lrcv-1683281154819)(C:\Users\spring\AppData\Roaming\Typora\typora-user-images\image-20230505150452996.png)]

    3. 并且不健康之后并不会被踢出

  6. nacos集群采用ap,如果有非临时实例,切换到cp,eureka采用ap

os主动发送请求,问你还活着不,用来健康检测。如果没有回复,不会踢掉,会保留,等恢复。

  1. 消费者的也会有差距

    1. eureka拉取列表的时候并不知道健康状态,因为是心跳检测,可能不及时
    2. nacos消费者会定时拉取,同时如果列表变化,那么nacos注册中心会主动发送信息,告知消费者列表变化,更加及时。
  2. 修改是否是临时实例

    1.   cloud:
          nacos:
            server-addr: localhost:8848
            discovery:
              cluster-name: HZ
              namespace: bec1d56c-b966-4c23-9641-4a70d1cc5530
              ephemeral: false # 非临时实例
      
    2. [外链图片转存中…(img-Xg39Lrcv-1683281154819)]

    3. 并且不健康之后并不会被踢出

  3. nacos集群采用ap,如果有非临时实例,切换到cp,eureka采用ap

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GGUOHHUO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值