SpringCloud第六篇-Zuul

Zuul之身份认证 Zuul之身份认证 微服务架构所面临的问题? 1)针对某个功能,客户端在微服务架构的情况下需要请求多个模块接口 2)针对于身份认证、日志、流量控制等公共模块每个微服务都需要做一遍,不利于业务与非业务的拆分 Zuul可以做什么 1)客户端只需要知道网关而不需要知道具体模块的地址,所有服务由网关对外提供 2)身份认证类的东西单独抽象出来,业务模块只做业务 3)易于监控。可在微服务网... 阅读详情

Zuul简介

Zuul可以通过加载动态过滤机制,从而实现以下各项功能:

  • 验证与安全保障: 识别面向各类资源的验证要求并拒绝那些与要求不符的请求。
  • 审查与监控: 在边缘位置追踪有意义数据及统计结果,从而为我们带来准确的生产状态结论。
  • 动态路由: 以动态方式根据需要将请求路由至不同后端集群处。
  • 压力测试: 逐渐增加指向集群的负载流量,从而计算性能水平。
  • 负载分配: 为每一种负载类型分配对应容量,并弃用超出限定值的请求。
  • 静态响应处理: 在边缘位置直接建立部分响应,从而避免其流入内部集群。
  • 多区域弹性: 跨越AWS区域进行请求路由,旨在实现ELB使用多样化并保证边缘位置与使用者尽可能接近。

除此之外,Netflix公司还利用Zuul的功能通过金丝雀版本实现精确路由与压力测试。

在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、断路器、智能路由、配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统。一个简答的微服务系统如下图:

这里写图片描述
注意:A服务和B服务是可以相互调用的,作图的时候远作者方志朋忘记了。并且配置服务也是注册到服务注册中心的。

在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul、Ngnix),再到达服务网关(zuul集群),然后再到具体的服。,服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理(下一篇文章讲述),配置服务的配置文件放在git仓库,方便开发人员随时改配置。

更加典型的结构图如下

在这里插入图片描述

项目准备

  • 运行注册中心eureka-server
  • 修改home方法,并运行service-hello:只用运行一个就可以了

改写home方法如下:方便后面的请求的不同

public String home(String name ) {
        return "hello "+name+"from port:" +port;
    }
  • 修改service-ribbon下的HelloService方法,运行service-ribbon
    修改部分如下,name参数加入ribbon_前缀
 public String helloService(String name) {
         return restTemplate.getForObject("http://SERVICE-HELLO/hello?name=ribbon_"+name,String.class);
        //return restTemplate.getForObject("http://SERVICE-HELLO/hello",String.class);
    }
  • 运行service-feign

通过运行http://desktop-180i6sh:8764/hello?name=bamboo
http://desktop-180i6sh:8765/hello?name=bamboo
我们可也看出返回的字符串区别,加了ribbon_前缀的是从service-ribbon请求过去,而没有加的则是service-feign请求过去

hello ribbon_bamboofrom port:8762
hello bamboofrom port:8762
  • service-zuul:新建项目

创建service-zuul工程

另起一个project,取名叫service-zuul

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.bamboo</groupId>
    <artifactId>service-zuul</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.RC1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>


</project>
yml

application.yml

server:
  port: 8769
spring:
  application:
    name: service-zuul
    #服务名为service-zuul;

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/


#以/api-a/ 开头的请求都转发给service-ribbon服务;以/api-b/开头的请求都转发给service-feign服务
zuul:
	# strip-prefix: true  #请求转发时去掉转发路径(path中的值)/api-a/hello会转成/hello
  routes:
    api-a:
      path: /api-a/**
      serviceId: service-ribbon
    api-b:
      path: /api-b/**
      serviceId: service-feign



指定服务注册中心的地址为http://localhost:8761/eureka/,服务的端口为8769,服务名为service-zuul;以/api-a/ 开头的请求都转发给service-ribbon服务;以/api-b/开头的请求都转发给service-feign服务;

配置扩展

zuul:
  ignored-services: * #忽略所有路由,基本无法访问,忽略某些可以有逗号分隔
  prefix: /api #所有请求都需要加上这个前缀
  ignoredPatterns: /**/admin/** 过滤掉path包含admin的请求
  routes:
    spring-boot-user:
      path: /user/**
      strip-prefix: false # 是否忽略路由前缀,默认true忽略前缀prefix
      url: forward: www.baidu.com # /user/***路径都转发到www.baidu.com

一般访问方式,这种方式是可以负载均衡的(避免直走)
路由地址:端口/服务名称/ 访问路径

zuul.prefix: 我们可以指定一个全局的前缀
strip-prefix: 是否将加上代理前缀,默认是true,false时

通过api/访问user服务:
http://zuul:8050/api/spring-boot-user/user/1

prefix注释掉后,eg如下
strip-prefix默认为true
http://zuul:8050/spring-boot-user/user/1
strip-prefix:false时都可以,前提是多个服务的路径不会冲突
http://zuul:8050/spring-boot-user/user/1
http://zuul:8050/user/1

更多详细解读请参看:
https://www.iteye.com/blog/huan1993-2424676

java

package com.bamboo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

/**
 *
 *
 * Created by bamboo on 2017/10/24.
 * 更新注释2020/6/11
 */
//启动类加上注解@EnableZuulProxy
//它默认加上了@EnableCircuitBreaker和@EnableDiscoveryClient
@EnableZuulProxy
@SpringBootApplication
public class ZuulApplication {

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


}

启动运行并查看结果

依次启动上面的项目,服务如下
这里写图片描述

打开浏览器访问:http://localhost:8769/api-a/hello?name=bamboo ;浏览器显示:

hello ribbon_bamboofrom port:8762

http://localhost:8769/api-b/hello?name=bamboo ;浏览器显示:

hello ribbonfrom port:8762

通过返回的字符串我们知道,service-zuul根据路径把请求发送到不同的服务上了,因此路由转发的功能是确定的。

zuul拦截器:服务授权过滤

相当于servlet中的filter拦截器功能,但是显然要比它强大。
创建MyFilter.java,实现一个简单的接口授权功能

package com.bamboo;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 *
 * zuul不仅只是路由,并且还能过滤,做一些安全验证
 * Created by xialeme on 2017/10/24.
 */
@Component
public class MyFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(MyFilter.class);
    @Override
    public String filterType() {
        return "pre";//路由之前
    }

    @Override
    public int filterOrder() {
        return 0;
    }

/**
     * 过滤器是否生效
     * 返回true则会进入run方法中执行
     *返回false则说明不需要过滤直接返回请求路径的结果
     * @return
     */
    @Override
    public boolean shouldFilter() {
    
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        //System.out.println(request.getRequestURI()); ///apigateway/product/api/v1/product/lis
        // System.out.println(request.getRequestURL()); //http://localhost:9000/apigateway/product/api/v1/product/list
        //ACL

        log.info("权限检查:{}", request.getRequestURI());
        //符合以下路径的则需要进行过滤,否则直接返回请求路径的结果
        if ("/apigateway/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        } else if ("/apigateway/order/api/v1/order/list".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        } else if ("/apigateway/order/api/v1/order/find".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        }else if ("/sys-admin/group/1".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        }
        return false;
    }


    //过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
        Object accessToken = request.getParameter("token");//获取请求中的token参数
        if(accessToken == null) {
            log.warn("token is empty");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            try {
                ctx.getResponse().getWriter().write("token is empty");
            }catch (Exception e){}

            return null;
        }
        log.info("ok");
        return null;
    }
}

filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
pre:路由之前
routing:路由之时
post: 路由之后
error:发送错误调用
filterOrder:过滤的顺序
shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。

这时访问:http://localhost:8769/api-a/hello?name=forezp ;网页显示:

token is empty

加上token再试一次
http://desktop-180i6sh:8769/api-a/hello?name=bamboo&token=111

hello ribbon_bamboofrom port:8762

接口访问成功了

JWT和spring sercurity都是可以在zuul中实现权限的拦截和判断,进入整合进授权过滤功能中

参考资料

zuul官网
方志朋-史上最简单的SpringCloud教程 | 第五篇: 路由网关(zuul)

SpringCloud之Zuul使用 Zuul 是 Netflix 开源的微服务网关,Spring Cloud 对 Zuul 进行了整合和增强。在 SpringCloud 体系中,Zuul 担任着网关的角色,对发送到服务端的请求进行一些预处理,比如安全验证、动态路由、负载分配等。 Zuul 的核心是 Filters,根据执行时期,Filters 分为以下几类: PRE:这种过滤器在请求被路由之前调用 ROUTING:这种过滤器将... 阅读详情

相关推荐

SpringCloud之Zuul的使用实例

Zuul是Netflix开源的API Gateway微服务网关,可以和Eureka、Ribbon、Hystrix等组件配合使用,Spring Cloud对Zuul进行了整合与增强。Zuul的主要功能是路由转发和过滤器。zuul默认和Ribbon结合实现了负载均衡的功能 所有从设备或网站来的请求都会经过Zuul到达后端的Netflix应用程序 搭建Zuul服务 1.新建一个springcloud-zuul模块,引入依赖 <dependency> ..

qq_37133859的博客 944

一篇掌握SpringCloud之服务网关zuul

Zuul:维基百科:电影《捉鬼敢死队》中的怪兽,Zuul,在纽约引发了巨大骚乱。事实上,在微服务架构中,Zuul就是守门的大Boss!一夫当关,万夫莫开!!Spring Cloud Zuul路由是微服务架构的不可或缺的一部分,提供动态路由,监控,弹性,安全等的边缘服务。Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器。zuul 是netflix开源的一个API Gateway 服务器, 本质上是一个web servlet应用。

haidi8 554

SpringCloud Netflix复习之Zuul

从源码的角度看下Zuul的路由转发和多个阶段的过滤器执行原理。

bazhuayu_1203的博客 1418

微服务教程5:spring-cloud 的Zuul 官网 的用法

今天,来记录Zuul ,spring cloud 的网关组件的使用方法 Zuul 的使用场景,就是api的一个入口,当某些权限验证,以及过滤器 等 ,都在此处做处理; 1, 先创建 Zuul 的项目 <?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"

weixin_39285027的博客 2万+

微服务实战系列(六)-网关springcloud zuul

1. 场景描述 今天接着介绍springcloud,今天介绍下springcloud的路由网关-Zuul,外围系统或者用户通过网关访问服务,网关通过注册中心找到对应提供服务的客户端,网关也需要到注册中心进行注册。 2. 解决方案 2.1 官网架构图 先把官网的图在贴一下,便于理解。 说明: gateway负责与外部进行交互,是sprincloud微服务对外的窗口。 2.2 开始撸码 2.2.1 new—>project 2.2.2 选择组件 (1)注册客户端 (2)路由Zuul next-&g

软件老王 689

springcloud-路由Zuul

1. 场景描述 今天接着介绍springcloud,今天介绍下springcloud的路由网关-Zull,外围系统或者用户通过网关访问服务,网关通过注册中心找到对应提供服务的客户端,网关也需要到注册中心进行注册。 2. 解决方案 2.1 官网架构图 先把官网的图在贴一下,便于理解。 说明: gateway负责与外部进行交互,是sprincloud微服务对外的窗口。 2.2 开始撸码 2.2.1 ...

软件老王 4383

Zuul网关简介以及使用

路由是微服务架构的一个组成部分。例如,`/`可能映射到您的 Web 应用程序、`/api/users`映射到用户服务和`/api/shop`映射到商店服务。 Zuul是来自 Netflix 的基于 JVM 的路由器和服务器端负载均衡器。

怪咖@的博客 1万+

spring cloud oauth2 zuul 单点登录 认证授权

spring cloud框架下的单点登录sso技术 oauth2实现的认证 授权 以及zuul作为网关路由 可以参考学习使用

springcloud教程 -- 4.网关zuul的使用详解

zuul

叶巨岩的博客 5672

spring cloud + shiro集成方案

手把手教你集成spring cloud + shiro微服务框架;用最少的工作量,改造基于shiro安全框架的微服务项目,实现spring cloud + shiro 框架集成。博客地址:https://blog.youkuaiyun.com/weixin_42686388/article/details/103084289

保姆级教程:用Protege 5.5.0从零构建你的第一个知识图谱(附实战案例文件)

本文提供了一份详细的Protege 5.5.0使用指南,从零开始构建知识图谱。涵盖环境配置、本体结构设计、实例填充到可视化展示的全流程,特别适合初学者快速掌握知识建模技术。通过实战案例演示,帮助读者理解如何定义类、属性及建立实例关系,是学习知识图谱构建的实用教程。

weixin_42548816的博客 553

(第六篇)Springcloud之Zuul路由网关

Zuul包含了对请求的路由和过滤两个最主要的功能,路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础.Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,以后访问微服务都是通过Zuul跳转后获得。GitHub地址。

hk000001的博客 384

VFIO框架源码分析(二十一)- IOMMUFD 模式下的 DMA 映射机制

在虚拟化 I/O 的世界里,无论上层管理面(如对象模型、设备绑定)如何重构,数据面最核心的任务始终未变——DMA 映射(DMA Mapping)。即如何建立 Guest Physical Address (GPA) 到 Host Physical Address (HPA) 的映射关系,并将其填入 IOMMU 的硬件页表中,使得直通设备能够正确访问虚拟机内存。在 Legacy VFIO (Type1) 时代,这一职责由承担,它通过ioctl 操作 Container。

qq_36071928的博客 1007

Spring Cloud系列之 第六篇:服务网关zuul快速入门

通过Zuul,我们可以实现请求的路由、负载均衡和权限控制等功能。其中,spring.application.name指定服务的名称,server.port指定服务的端口号,eureka.client.serviceUrl.defaultZone指定Eureka Server的地址。其中,spring.application.name指定服务的名称,server.port指定服务的端口号,eureka.client.serviceUrl.defaultZone指定Eureka Server的地址。

good7ob的博客 142

libcurl库使用详情、libcurl库的制作

​ libcurl是一个跨平台的网络协议库,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传, HTTP基本表单上传,代理,cookies,和用户认证。libcurl的官网 、库下载。这种库使用的时候就像使用wiringPi库一样,编写完代码需要链接这个库,所以要先下载这个库。libcurl的使用(其实和socket编程时一样,都需要一定的步骤):

qq_45698138的博客 5337

MS2107 CVBS转USB2.0 音视频采集芯片,支持1080P@30HZ输出

MS2107 是一款视频和音频采集芯片,支持CVBS转USB2.0 ;可以将 CVBS、S-Video 和音频信号通过 USB接口传送到 PC、智能手机和平板电脑上预览或采集。

TEL18967112838的博客 2075

SpringCloud学习第六篇:Zuul学习(Hoxton.SR4)

一、什么是Zuul Zuul作为微服务系统的网关组件。所有从设备或网站来的请求都会经过Zuul到达后端,用于构建边界服务,致力于动态路由、过滤、监控、弹性伸缩和安全。Zuul底层利用各种filter来实现如:认证和安全、性能检测、动态路由、压力测试、负载均衡、静态资源处理。 二、Zuul和Nginx的区别 相同点 Zuul和Nginx都可以实现负载均衡、反向代理(隐藏真实ip地址),过滤请求,实...

无话可说丶 287

kali攻防第2章 内网称霸之渗透安卓系统

Kali内网称霸之渗透安卓系统   准备工具   1、准备一部实体android手机 2、使用KALI系统     要用到强大的msf工具(metasplot)   流程步骤 1、启动msf命令是msfconsole 2、在安卓手机上安装一个自己生成的apk木马程序 3、利用msf工具来远程连接Android系统   1)启动msf(注意这里是链接msf就行了不需要进

安全参透之旅 1万+

Spring Cloud教程 | 第六篇:路由网关(Zuul的路由转发及过滤器用法)

题记: 在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、断路器、智能路由、配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统。一个简单的微服务系统如下图: 在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul、Ngnix),再到达服务网关(zuul集群),然后再到具体的服。服务统...

刘军的博客 9019

《DeepJIT: An End-To-End Deep Learning Framework for Just-In-Time Defect Prediction》论文笔记

软件工程任务:即时缺陷预测(涉及SE+AI知识)

weixin_43646592的博客 701

13、混合系统的离散与连续交互

本文详细探讨了混合系统中离散事件与连续动态的交互机制,涵盖了建模方法、分析技术、设计挑战以及多种控制策略。通过具体案例研究和操作语义的定义,展示了混合系统在制造业、交通系统、机器人技术和过程控制等领域的广泛应用。文章还介绍了实验仿真、稳定性研究及优化方法,旨在帮助读者全面理解混合系统的设计与控制要点,并为未来智能化和自适应混合系统的发展提供了展望。

5f4d3s2a1q的博客 126

springCloud网关Zuul和GateWay区别

getway和zuul在zuul没有进行参数调优的时候,getway的性能会远高于zuul。 分析,在空负载的时候,SpringCloud Gateway比zuul 1 性能高50%左右,在模拟处理50ms业务后,,SpringCloud Gateway比zuul 1 性能高9倍左右。 但是考虑到zuul使用默认配置,结果可能不准,上网查找zuul生产优化配置调优后再次进行50ms业务处理压测。而SpringCloud Gateway查阅资料后暂无需优化。 zuul优化参数参考如下: 性能比较结论 在实

joy_tom的博客 2万+

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

深入理解SpringCloud之Zuul

在Zuul中,过滤器扮演着极其关键的角色,它们负责在请求路由的各个阶段执行各种任务,比如安全认证、请求日志记录、参数校验等。通过自定义过滤器,咱们可以实现更加复杂和定制化的逻辑来满足特定的业务需求。下面,小黑将带领咱们一探究竟,如何编写和使用自定义过滤器。要创建一个自定义过滤器,咱们需要继承ZuulFilter和run()。preroutepost和error。:返回一个int值来指定过滤器的执行顺序,数值越小,优先级越高。:返回一个布尔值,判断该过滤器是否需要执行。run():过滤器的具体逻辑。

宋小黑的博客 2671

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

上一篇: SpringCloud第五篇-Hystrix Dashboard
下一篇: SpringCloud第七篇-Spring Cloud Config
牧竹子
博客等级 码龄17年 572粉丝 233原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值