为了账号安全,请及时绑定邮箱和手机立即绑定

Gateway引入学习:简单教程入门

概述

Gateway是一种位于客户端和服务器之间的网络基础设施组件,其主要职责是接收和转发请求,并根据预定义的规则将请求路由到合适的后端服务。本文详细介绍了Gateway的作用、应用场景、安装部署、基本使用方法以及高级功能,如动态路由、权重路由和限流降级。此外,还提供了常见问题的解决方法和性能优化技巧。通过本文,您可以全面了解如何引入和使用Gateway,从而提升系统的灵活性和性能。

Gateway简介

什么是Gateway

Gateway是一种高级的网络基础设施组件,它位于客户端和服务器之间,充当二者之间的中介。Gateway的主要职责是接收客户端请求,根据一定的规则将请求转发到后端合适的服务器,并返回响应结果。Gateway通常用于服务的集成、负载均衡、路由、安全控制等多种场景。

Gateway可以被视作一个强大的路由器或代理服务器,它能够根据一系列预定义的路由规则,将来自客户端的请求转发到不同的后端服务。这种设计使得多个客户端能够通过统一的接口访问不同的服务,而不需要了解具体的服务地址和端口。

在现代的分布式系统架构中,Gateway不仅简化了客户端与服务之间的交互,还提供了丰富的功能,如安全认证、请求过滤、负载均衡、服务发现等,以提升系统的安全性、可靠性和可维护性。

Gateway的作用和应用场景

Gateway在分布式系统架构中扮演着至关重要的角色。下面是Gateway的一些主要作用及其应用场景:

  1. 负载均衡:Gateway可以通过负载均衡策略将客户端请求分发到多个后端服务实例上,从而实现请求的均匀分布。这不仅提高了系统的处理能力,还能保证单个服务实例不会过载。例如,假设有一个电子商务平台,其订单处理服务可以通过Gateway进行请求的负载均衡,确保每个订单处理服务实例能够处理相对均匀的请求量。

  2. 服务发现和路由:在微服务架构中,每个服务实例通常会有动态的IP地址和端口。Gateway可以自动发现服务实例,并根据预配置的路由规则,将请求转发到正确的服务实例上。这种方式降低了服务之间的耦合度,并简化了服务之间的通信。例如,通过使用服务发现机制,Gateway可以动态地更新路由规则,从而实现对服务实例的自动发现和路由。

  3. 协议转换:Gateway可以处理从HTTP、HTTPS到其他协议(如WebSocket或gRPC)的转换。这使得前端应用和服务之间的通信更加灵活。例如,假设有一个前端应用需要与一个只支持WebSocket协议的后端服务进行通信。Gateway可以将前端的HTTP请求转换为WebSocket消息,从而实现协议的无缝转换。

  4. 安全控制:Gateway可以提供多种安全措施,包括认证、鉴权、速率限制等。这有助于保护后端服务免受未授权的访问和服务滥用。例如,Gateway可以实现基于OAuth的认证机制,确保只有合法的客户端才能访问后端服务。此外,还可以实施API限流策略,防止恶意用户或爬虫暴力访问。

  5. 请求过滤和路由匹配:Gateway可以根据请求的URL、HTTP方法、参数等信息进行过滤和路由匹配,从而实现更细粒度的控制。例如,可以配置Gateway,使得只有在特定时间窗口内的请求才会被转发到后端服务。这有助于实现对特定场景的精准控制和优化。

通过这些功能,Gateway不仅简化了客户端和服务之间的交互,还增强了系统的灵活性和可维护性。无论是分布式系统还是微服务架构,Gateway都是不可或缺的一部分。

Gateway与传统网关的区别

Gateway与传统网关在概念上有一定的交叠,但它们的设计目的和实现细节有所不同。以下是Gateway与传统网关的主要区别:

  1. 设计目的:传统网关主要是为了实现网络通信的基本功能,如路由、协议转换和简单的安全控制。而Gateway不仅继承了传统网关的功能,还增加了许多高级特性,如服务发现、负载均衡、动态路由和请求过滤等。这种增强使得Gateway在现代分布式系统中扮演着更为重要的角色。

  2. 灵活性和扩展性:Gateway设计时充分考虑了灵活性和扩展性。它通常采用插件化的架构,可以方便地添加或移除特定功能,以适应不同的应用场景。而传统网关通常具有固定的功能集,难以进行扩展或修改。例如,可以通过插件的形式为Gateway添加认证插件或限流插件,从而实现更为灵活的安全控制和流量管理。

  3. 配置管理:Gateway通常支持动态配置管理,可以实时更新路由规则、过滤器和负载均衡策略等。这使得系统管理员能够根据业务需求快速调整Gateway的行为。而传统网关的配置管理相对静态,一旦配置好后,更改配置通常需要重启服务或更新配置文件。

  4. 服务发现和负载均衡:Gateway在服务发现和负载均衡方面有着更强大的能力。它可以自动发现服务实例,并根据服务的健康状态动态调整负载均衡策略。这对于微服务架构中的服务治理尤为重要。而传统网关通常不支持服务发现,只能基于固定的IP地址和端口进行路由。

  5. 协议支持:除了常见的HTTP协议,Gateway还支持多种协议,如gRPC、WebSocket等。它能够实现协议之间的转换,从而满足不同应用场景的需求。而传统网关通常只支持基本的HTTP协议,对于更复杂或特定的协议支持较少。

通过这些区别,可以看出Gateway在灵活性、动态配置管理、服务发现和协议支持等方面相比传统网关具有显著的优势。这使得Gateway在现代分布式系统和服务架构中扮演了更为重要的角色。

Gateway的基本组件

路由配置

路由配置是Gateway的核心功能之一。通过路由配置,Gateway可以将客户端的请求发送到合适的后端服务。下面是路由配置的基本概念和示例代码:

  1. 路由匹配:Gateway会根据路由规则,匹配客户端请求的URL、HTTP方法、请求头等信息,然后将请求转发到对应的后端服务。路由匹配通常遵循特定的模式和规则。

  2. 路由规则:路由规则定义了如何将请求转发到后端服务。通常包括路由的ID、匹配的URL路径、目标服务地址等信息。下面是一个简单的路由配置示例:
spring:
  cloud:
  gateway:
    routes:
    - id: user-service # 路由的唯一标识
      uri: http://localhost:8080 # 目标服务的地址
      predicates:
      - Path=/users/** # 匹配的URL路径
      filters:
      - RewritePath=/users/([^/]+), /user-service/$1 # 重写路径

在这个示例中,路由规则定义了/users/**路径的所有请求都会被转发到http://localhost:8080服务。此外,还定义了一个路径重写规则,将/users/路径重写为/user-service/

  1. 路由优先级:如果有多个路由规则匹配同一个请求,可以通过设置路由的优先级来决定哪个规则会被应用。优先级值越低,优先级越高。例如:
spring:
 cloud:
  gateway:
    routes:
    - id: user-service
      uri: http://localhost:8080
      predicates:
      - Path=/users/**
      filters:
      - RewritePath=/users/([^/]+), /user-service/$1
      order: 1 # 设置优先级为1

在这个示例中,order属性为1,表示该路由具有较高的优先级。

  1. 路由组:为了更好地组织和管理路由规则,可以将路由分组。每个路由组可以包含多个路由规则。例如:
spring:
 cloud:
  gateway:
    routes:
    - id: user-service
      uri: http://localhost:8080
      predicates:
      - Path=/users/**
      filters:
      - RewritePath=/users/([^/]+), /user-service/$1
      order: 1
    - id: product-service
      uri: http://localhost:8081
      predicates:
      - Path=/products/**
      filters:
      - RewritePath=/products/([^/]+), /product-service/$1
      order: 2

在这个示例中,定义了两个路由规则,分别对应/users/**/products/**路径,每个规则都有独立的优先级。

通过以上示例和配置,可以清晰地看到如何定义和管理路由规则,以便将客户端请求发送到合适的后端服务。

服务发现

服务发现是Gateway的重要功能之一,它可以帮助Gateway动态地识别和配置后端服务的地址和端口。服务发现通常通过注册中心(如Eureka、Consul等)来实现。

  1. 服务注册和发现机制:后端服务实例会向注册中心注册自己的地址和端口,注册中心会维护一个服务实例的列表。Gateway会从注册中心获取服务实例的信息,并根据这些信息动态地更新路由规则。

  2. 示例代码:假设使用Eureka作为注册中心,可以通过以下配置实现服务发现功能:
spring:
  cloud:
  gateway:
    discovery:
      locator:
        enabled: true # 开启服务发现功能
        enabled-by-default: true # 默认开启服务发现功能
        lookup-service-id: gateway-service # 指定服务ID(可选)
  eureka:
    client:
      service-url:
        defaultZone: http://localhost:8761/eureka/ # 注册中心地址

在这个示例中,配置了Gateway启用服务发现功能,并指定了Eureka注册中心的地址。在实际应用中,需要确保所有的服务实例都注册到Eureka,这样Gateway才能从注册中心动态获取服务实例的信息。

通过服务发现机制,Gateway可以在服务实例动态变化时自动更新路由规则,从而保证系统的高可用性。

故障转移

故障转移是Gateway提供的另一个重要功能,它可以在后端服务实例出现故障时,自动将请求转发到其他可用的服务实例。故障转移机制帮助系统在服务故障时保持稳定运行。

  1. 负载均衡策略:Gateway通常支持多种负载均衡策略,如轮询(Round Robin)、最少连接(Least Connections)等。这些策略可以根据后端服务的状态和负载情况动态调整请求的分发。

  2. 健康检查:为了实现故障转移,Gateway需要定期检测后端服务的健康状态。这可以通过配置健康检查策略来实现,例如,检查服务响应时间、错误率等指标。

  3. 示例代码:以下是一个简单的配置示例,使用了Nginx作为后端服务:
spring:
 cloud:
  gateway:
    routes:
    - id: my-service
      uri: http://backend-service # 后端服务的地址
      predicates:
      - Path=/api/**
      filters:
      - name: LoadBalancer # 使用负载均衡器
      - name: CircuitBreaker # 使用断路器
        args:
          fallback-uris: /api/fallback # 定义降级策略

在这个示例中,LoadBalancer过滤器用于实现负载均衡,CircuitBreaker过滤器用于实现断路器功能。当后端服务出现故障时,请求会被重定向到降级策略定义的URI /api/fallback

通过这些配置,Gateway在检测到服务故障后,可以自动将请求转发到其他可用的服务实例,从而实现故障转移和系统的高可用性。

Gateway的安装和部署

环境准备

在安装和部署Gateway之前,需要确保开发环境已经满足相关要求:

  1. Java环境:Gateway基于Spring Cloud构建,需要Java环境。建议使用Java 11及以上版本。
  2. 依赖管理工具:使用Maven或Gradle作为依赖管理工具。
  3. 开发工具:IDEA或Eclipse等集成开发环境。
  4. 注册中心(可选):如果需要服务发现功能,需要安装和配置Eureka、Consul等注册中心。

安装和部署Gateway时需要确保系统已经安装了Java环境,建议使用Java 11及以上版本。此外,还需要确保开发工具和依赖管理工具已经安装和配置好。如果需要服务发现功能,还需要安装和配置注册中心。下面是一个简单的环境准备步骤:

  1. 安装Java环境

    • 下载Java 11及以上版本的安装包。
    • 安装Java环境,并设置环境变量。
    • 验证安装是否成功,可以通过命令java -version来检查Java版本。
  2. 安装Maven或Gradle

    • 下载Maven或Gradle的安装包。
    • 解压安装包,并设置环境变量。
    • 验证安装是否成功,可以通过命令mvn -vgradle -v来检查版本。
  3. 安装IDEA或Eclipse

    • 下载并安装IDEA或Eclipse。
    • 打开IDEA或Eclipse,创建一个新的Spring Boot项目。
  4. 安装注册中心(可选)
    • 如果需要服务发现功能,需要安装和配置Eureka或Consul。
    • 下载并安装注册中心服务。
    • 配置注册中心服务,启动注册中心。

通过以上步骤,可以确保开发环境已经准备好,可以开始安装和部署Gateway。

安装步骤

安装Gateway通常涉及创建一个Spring Boot项目,并在项目中添加必要的依赖。下面是详细的安装步骤:

  1. 创建Spring Boot项目

    • 使用IDEA或Eclipse创建一个新的Spring Boot项目。
    • pom.xml(对于使用Maven的项目)或build.gradle(对于使用Gradle的项目)中添加必要的依赖。
  2. 添加依赖
    • 添加Spring Cloud Gateway的依赖。对于Maven项目,可以在pom.xml中添加以下依赖:
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
  • 对于Gradle项目,可以在build.gradle文件中添加以下依赖:
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
  1. 配置应用
    • application.ymlapplication.properties文件中配置应用的基本信息,如端口号和服务器地址。
server:
 port: 8080 # 设置服务器端口
  1. 启动应用
    • 使用IDEA或Eclipse启动Spring Boot应用。
    • 验证应用是否成功启动,可以通过访问http://localhost:8080来检查。

通过以上步骤,可以成功安装和启动一个Spring Cloud Gateway应用,并确保它可以正常运行。

部署示例

部署Gateway应用到生产环境通常涉及在服务器上安装Java环境、部署应用、配置应用参数等步骤。下面是详细的部署示例:

  1. 安装Java环境

    • 在服务器上安装Java环境,确保已经设置好环境变量。
    • 验证Java环境已经安装成功,可以通过命令java -version来检查。
  2. 打包应用

    • 在开发环境打包Spring Boot应用。可以通过命令mvn clean packagegradle build来打包应用。
    • 打包完成后,会在项目的targetbuild目录下生成一个.jar.war文件。
  3. 部署应用
    • 将打包好的应用文件上传到服务器。
    • 使用命令行工具启动应用,例如:
java -jar gateway-app.jar --spring.profiles.active=prod
  • 其中,gateway-app.jar是打包好的应用文件,--spring.profiles.active=prod指定了激活的配置文件为prod
  1. 配置应用参数
    • 根据生产环境的需求配置应用参数,例如设置端口号、服务器地址等。
    • 可以通过环境变量或配置文件来设置参数。例如,在application.yml中添加:
server:
 port: 80 # 设置生产环境的端口号
  1. 监控和管理
    • 使用监控工具如Prometheus或Zabbix来监控应用的运行状态。
    • 配置日志管理工具,例如使用Logstash和Elasticsearch来收集和分析日志。

通过以上步骤,可以将Gateway应用成功部署到生产环境,并确保它可以正常运行。

Gateway的基本使用

创建路由规则

创建路由规则是配置Gateway的最基本操作之一。通过路由规则,Gateway可以将客户端的请求发送到相应的后端服务。下面是创建路由规则的步骤和示例代码:

  1. 定义路由规则

    • 在Spring Boot应用中,路由规则通常定义在application.ymlapplication.properties文件中。
    • 使用spring.cloud.gateway.routes配置路由规则。
  2. 示例代码
    • 下面是一个简单的配置示例,定义了一个路由规则将/users/**路径的请求转发到http://localhost:8080服务。
spring:
 cloud:
 gateway:
    routes:
    - id: user-service
      uri: http://localhost:8080
      predicates:
      - Path=/users/**
      filters:
      - RewritePath=/users/([^/]+), /user-service/$1

在这个示例中,定义了一个路由规则,其中:

  • id: user-service:路由规则的唯一标识。
  • uri: http://localhost:8080:目标服务的地址。
  • predicates: Path=/users/**:路由匹配条件,表示匹配/users/**路径的所有请求。
  • filters: RewritePath=/users/([^/]+), /user-service/$1:路径重写规则,将/users/路径重写为/user-service/

通过这样的配置,Gateway会将客户端发送到/users/**路径的请求转发到http://localhost:8080服务,并将路径进行重写。

配置过滤器

过滤器是Gateway中一个强大的组件,它允许在请求和响应之间插入一些逻辑处理,从而实现更细粒度的控制。过滤器通常用于请求过滤、响应处理、日志记录等场景。

  1. 过滤器类型

    • 请求过滤器:在请求到达后端服务之前执行,可用于认证、限流等。
    • 响应过滤器:在响应返回客户端之前执行,可用于日志记录、修改响应等。
  2. 示例代码
    • 下面是一个简单的过滤器配置示例,定义了一个请求过滤器和响应过滤器。
spring:
 cloud:
 gateway:
    routes:
    - id: user-service
      uri: http://localhost:8080
      predicates:
      - Path=/users/**
      filters:
      - name: RequestLogging # 请求过滤器,用于日志记录
      - name: ResponseLogging # 响应过滤器,用于日志记录
        args:
          logLevel: INFO # 设置日志级别为INFO

在这个示例中,定义了两个过滤器:

  • name: RequestLogging:请求过滤器,用于在请求到达后端服务之前记录日志。
  • name: ResponseLogging:响应过滤器,用于在响应返回客户端之前记录日志。
  • args: logLevel: INFO:设置日志级别为INFO

通过这种方式,可以灵活地添加和配置过滤器,以便实现各种逻辑处理。

使用断路器

断路器是Gateway中一个重要的组件,用于实现服务的故障隔离和容错。通过断路器,可以防止服务故障导致整个系统崩溃,从而提升系统的稳定性和可用性。

  1. 断路器原理

    • 断路器通过监控服务的健康状态(如请求失败率、响应时间等),在检测到服务故障时自动开启断路器。
    • 当断路器开启时,请求会被重定向到降级策略定义的URI,而不是发送到故障服务。
    • 断路器还可以设置自动恢复机制,当服务恢复正常时,自动关闭断路器。
  2. 示例代码
    • 下面是一个简单的断路器配置示例,定义了一个路由规则和断路器。
spring:
 cloud:
 gateway:
    routes:
    - id: user-service
      uri: http://localhost:8080
      predicates:
      - Path=/users/**
      filters:
      - name: CircuitBreaker # 使用断路器过滤器
        args:
          fallback-uris: /api/fallback # 定义降级策略
          exceptions: HttpClientErrorException # 指定异常类型
          fallback-order: 1 # 设置降级策略的优先级

在这个示例中,定义了一个路由规则,并使用断路器过滤器。其中:

  • id: user-service:路由规则的唯一标识。
  • uri: http://localhost:8080:目标服务的地址。
  • predicates: Path=/users/**:路由匹配条件。
  • filters: name: CircuitBreaker:使用断路器过滤器。
  • args: fallback-uris: /api/fallback:定义降级策略的URI。
  • exceptions: HttpClientErrorException:指定触发断路器的异常类型。
  • fallback-order: 1:设置降级策略的优先级。

通过这样的配置,Gateway会在检测到服务故障时自动开启断路器,将请求重定向到降级策略定义的URI,从而实现服务的故障隔离。

Gateway的高级功能

动态路由

动态路由是Gateway的一个高级功能,允许路由规则根据业务需求实时调整。动态路由可以通过编程方式或配置中心实现,使得系统能够根据外部条件动态调整路由策略。

  1. 动态路由的配置

    • 动态路由通常通过Spring Cloud Config或Consul等配置中心实现。
    • 可以在配置中心定义路由规则,并通过Gateway从配置中心获取路由配置。
  2. 示例代码
    • 下面是一个简单的动态路由配置示例,通过配置中心获取路由规则。
spring:
 cloud:
 gateway:
    routes:
    - id: user-service
      uri: http://localhost:8080
      predicates:
      - Path=/users/**
      filters:
      - name: RewritePath
        args:
          regex: /users/([^/]+)
          replacement: /user-service/$1

在这个示例中,定义了一个路由规则,并通过配置中心动态获取路由配置。通过这种方式,可以在配置中心实时调整路由规则,而无需重启Gateway应用。

权重路由

权重路由是Gateway的一个高级功能,允许根据服务的权重动态调整负载均衡策略。通过权重路由,可以实现更细粒度的流量控制,确保服务的负载均衡。

  1. 权重路由的配置

    • 在路由规则中,可以配置服务的权重,权重值越高表示服务优先级越高。
    • 可以使用LoadBalancer过滤器实现权重路由。
  2. 示例代码
    • 下面是一个简单的权重路由配置示例,定义了两个服务的权重。
spring:
 cloud:
 gateway:
    routes:
    - id: user-service
      uri: http://user-service
      predicates:
      - Path=/api/users/**
      filters:
      - name: LoadBalancer
        args:
          weight: 80 # 设置权重为80%
    - id: product-service
      uri: http://product-service
      predicates:
      - Path=/api/products/**
      filters:
      - name: LoadBalancer
        args:
          weight: 20 # 设置权重为20%

在这个示例中,定义了两个服务的路由规则,并设置了不同的权重。user-service的权重为80%,product-service的权重为20%。

通过这种方式,可以在负载均衡时根据服务的权重动态调整请求的分发,确保服务的负载均衡。

限流和降级

限流和降级是Gateway的重要功能,用于保护系统免受过载或恶意攻击的影响。通过限流和降级机制,可以实现对流量的控制和系统稳定性的保障。

  1. 限流配置

    • 可以使用RateLimiter过滤器实现请求的限流。
    • 通过配置限流规则,可以限制每个客户端的请求速率。
  2. 降级配置

    • 可以使用CircuitBreaker过滤器实现服务的降级。
    • 在检测到服务故障时,请求会被重定向到降级策略定义的URI。
  3. 示例代码
    • 下面是一个简单的限流和降级配置示例。
spring:
 cloud:
 gateway:
    routes:
    - id: user-service
      uri: http://localhost:8080
      predicates:
      - Path=/users/**
      filters:
      - name: RateLimiter # 使用限流过滤器
        args:
          key-resolver: ${spring.cloud.gateway.routes[0].filters[0].args.key-resolver}
          limit: 100 # 设置每秒请求限制为100
      - name: CircuitBreaker # 使用断路器过滤器
        args:
          fallback-uris: /api/fallback # 定义降级策略
          exceptions: HttpClientErrorException # 指定异常类型
          fallback-order: 1 # 设置降级策略的优先级

在这个示例中,定义了一个路由规则,并使用了限流和断路器过滤器。通过这种方式,可以限制客户端的请求速率,并在检测到服务故障时实现服务的降级。

Gateway的常见问题及解决方法

常见错误提示及其解决方法

在使用Gateway时,可能会遇到一些常见错误提示。下面是几个常见的错误提示及其解决方法:

  1. 404 Not Found

    • 错误提示404 Not Found表示请求的资源未找到。
    • 解决方法
      • 检查路由规则是否配置正确。
      • 确认后端服务地址是否正确。
      • 检查过滤器配置是否影响了请求的转发。
  2. 500 Internal Server Error

    • 错误提示500 Internal Server Error表示服务器内部错误。
    • 解决方法
      • 检查后端服务的日志,查看具体的错误信息。
      • 检查过滤器配置是否有误。
      • 确认服务端的异常处理逻辑是否正确。
  3. Gateway Filter does not support arguments

    • 错误提示Gateway Filter does not support arguments表示过滤器不支持传递参数。
    • 解决方法
      • 检查过滤器配置中的参数是否正确。
      • 确认过滤器名称是否正确。
      • 确认过滤器版本是否支持参数。
  4. 服务发现未启用
    • 错误提示服务发现未启用表示服务发现功能未配置。
    • 解决方法
      • 确认是否启用了服务发现功能。
      • 检查注册中心(如Eureka、Consul)的配置。
      • 确认服务实例已经注册到注册中心。

性能优化技巧

性能优化是确保Gateway应用高效运行的关键。下面是几个性能优化技巧:

  1. 合理配置请求缓存

    • 通过配置请求缓存,可以减少对后端服务的调用次数,提高系统性能。
    • 使用Cache过滤器实现请求缓存。
  2. 优化路由配置

    • 合理配置路由规则,避免规则重叠。
    • 确保路由规则能够准确匹配请求。
  3. 使用负载均衡策略

    • 合理配置负载均衡策略,确保请求能够均匀地分发到后端服务实例。
    • 使用LoadBalancer过滤器实现负载均衡。
  4. 启用服务发现
    • 使用服务发现机制可以动态地发现和管理后端服务实例,提高系统的灵活性和可维护性。

日志监控和分析

日志监控和分析是保障系统稳定运行的重要手段。通过日志监控和分析,可以及时发现和解决潜在问题。

  1. 配置日志记录

    • 配置日志记录,确保所有操作都有详细的日志记录。
    • 使用RequestLoggingResponseLogging过滤器实现请求和响应的日志记录。
  2. 使用性能监控工具

    • 使用Prometheus、Grafana等工具监控系统性能。
    • 配置监控指标,及时发现性能瓶颈。
  3. 分析日志数据
    • 使用Logstash、Elasticsearch等工具收集和分析日志数据。
    • 通过日志数据发现潜在的性能问题和异常情况。

通过以上方法,可以有效地监控和分析Gateway应用的日志数据,确保系统稳定运行。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消