【微服务】6、一篇文章学会使用 SpringCloud 的网关

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
传统型负载均衡 CLB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
简介: 【微服务】6、一篇文章学会使用 SpringCloud 的网关


一、网关作用

📗 身份认证、权限校验

📗 服务路由、负载均衡

📗 请求限流

二、网关的技术实现

📝 在 SpringCloud 中有两种网关的技术实现

✏️ gateway(比 zuul 新)

✏️ zuul

✒️ Zuul 是基于 Servlet 实现的,属于阻塞式编程

✒️ Gateway 是基于 Spring5 中提供的 WebFlux 实现的。属于响应式编程,具有更好的性能

三、简单使用

✏️ 网关是一个新的微服务

✏️ 需要通过 nacos 进行服务注册和发现

🎄 (1) 创建新的模块(module),引入 SpringCloudGateway 和 Nacos 服务发现依赖

<dependencies>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-gateway</artifactId>
      </dependency>
      <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
      </dependency>
  </dependencies>

🎄 (2)把网关服务注册到 nacos 中,并编写路由配置

server:
  port: 10010 # 网关服务的端口号
spring:
  application:
    name: gateway # 服务名
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos 服务发现地址
    gateway: # 网关相关配置
      routes: # 网关的路由配置
        - id: userservice # 路由编号(自定义), 保持唯一
          uri: lb://userservice # 路由的目标地址【lb: load balance】
          # uri: http://127.0.01:8081 # 路由的目标地址(直接写死)
          predicates: # 判断(断言)怎样的请求会被路由
            - Path=/users/** # 若请求路径是【/users/】开头的就路由到此
        - id: orderservice
          uri: lb://orderservice
          predicates:
            - Path=/orders/**

四、predicates

(1) 网关路由可配置的内容

✒️ id: 路由的唯一标识

✒️ uri:路由目的地【① lb: load balance;② http(不推荐)】

✒️ predicates:路由断言(判断请求是否符合要求,符合则路由转发到对应的 uri 的服务器)

✒️ filters:路由过滤器(处理请求响应

(2) 路由断言工厂(Route Predicate Factory)

📝 在配置文件中写的断言规则只是字符串(它会被 Predicate Factory 读取和处理,并转变为路由判断的条件)


✏️ Path=/user/** 是按照路径进行匹配

✏️ 是通过 PathRoutePredicateFactory 类来处理的


✏️ SpringCloudGateway 中的断言工厂:

五、filters

(1) GatewayFilter

📝 GatewayFilter 是网关中提供的一种过滤器(可对进入网关的请求和微服务的响应做处理)

官方提供了三十多种过滤器工厂:

https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories

(2) 给全部进入 userservice 的请求添加请求头

spring:
  application:
    name: gateway # 服务名
  cloud:
    gateway: # 网关相关配置
      routes: # 网关的路由配置
        - id: userservice # 路由编号(自定义), 保持唯一
          uri: lb://userservice # 路由的目标地址【lb: load balance】
          # uri: http://127.0.01:8081 # 路由的目标地址(直接写死)
          predicates: # 判断(断言)怎样的请求会被路由
            - Path=/users/** # 若请求路径是【/users/】开头的就路由到此
          filters: # 过滤器
            - AddRequestHeader=color, skyblue
        - id: orderservice
          uri: lb://orderservice
          predicates:
            - Path=/orders/**
@GetMapping("getUserById/{id}")
 public User getUserById(@PathVariable Long id,
                         @RequestHeader(value = "color", required = false) String color) {
     log.info("请求头: {}", color);
     return userService.getUserById(id);
 }

默认过滤器 default-filters 会对全部的路由请求都生效

spring:
  application:
    name: gateway # 服务名
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos 服务发现地址
    gateway: # 网关相关配置
      routes: # 网关的路由配置
        - id: userservice # 路由编号(自定义), 保持唯一
          uri: lb://userservice # 路由的目标地址【lb: load balance】
          # uri: http://127.0.01:8081 # 路由的目标地址(直接写死)
          predicates: # 判断(断言)怎样的请求会被路由
            - Path=/users/** # 若请求路径是【/users/】开头的就路由到此
#          filters: # 过滤器
#            - AddRequestHeader=color, skyblue
        - id: orderservice
          uri: lb://orderservice
          predicates:
            - Path=/orders/**
      default-filters: # 默认过滤器
        - AddRequestHeader=color, green

(3) 全局过滤器 —— GlobalFilter

📝 全局过滤器的作用: 处理一切进入网关的请求微服务响应,与GatewayFilter 的作用一样

📝 区别:GatewayFilter 通过配置定义,处理逻辑是固定的

📝 GlobalFilter 的逻辑需要自己写代码实现


📚 需求:定义全局过滤器,拦截并判断用户身份

定义全局过滤器,拦截请求。判断请求参数是否满足以下条件:

① 参数中是否有 authorization

② authorization 的参数值是否是 admin

若 ① 和 ② 同时满足,则放行;否则拦截

// @Order(value = 6) // 过滤器执行顺序(值越小,优先级越高)
@Component // 放入 IoC
public class GlobalGatewayFilter implements GlobalFilter , Ordered {
    /**
     * 拦截并处理全部的请求,处理成功后通过 chain 进入下一个过滤器
     *
     * @param exchange 请求上下文(可获取 Request、Response 等信息)
     * @param chain    放行该请求,进入下一过滤器
     * @return 返回,标识当前过滤器结束
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取请求参数
        // 该请求是 WebFlux 中的(与 HttpServletRequest 不同)
        ServerHttpRequest request = exchange.getRequest();
        // 获取请求参数(键值对)
        MultiValueMap<String, String> paramMap = request.getQueryParams();
        String paramVal = paramMap.getFirst("authorization");
        if (paramVal == null || !paramVal.equals("admin")) {
            // 拦截(返回)
            ServerHttpResponse response = exchange.getResponse();
            // 未登录状态码
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete(); // 返回
        }
        // 放行
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
        return 6;
    }
}

(4) 过滤器的执行顺序

📚 请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter

📚 请求路由后,会将当前路由过滤器、DefaultFilter、GlobalFilter 合并为一个过滤器链(集合)中,然后进行排序。排序之后,依次执行每个过滤器。


📚 每个过滤器都必须指定一个 int 类型的 order 值【order 值越小,优先级越高,执行顺序越靠前】

📚 GlobalFilter 通过实现 Ordered 接口或添加 @Order 注解来指定 order 值

📚 路由过滤器和 DefaultFilter 的 order 值由 Spring 指定【在各自过滤器内部按照声明顺序 从1 递增】

📚 当过滤器的 order 值一样时,优先级是:DefaultFilter > 路由过滤器 > GlobalFilter

server:
  port: 10010
spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: localhost:8848
    gateway:
      routes:
        - id: userservice
          uri: lb://userservice
          predicates:
            - Path=/users/**
          filters: # 路由过滤器
            - AddRequestHeader=color, red # order = 1
            - AddRequestHeader=color, blue # order = 2
            - AddRequestHeader=color, green # order = 3
      default-filters: # 默认过滤器
        - AddRequestHeader=name, zgq # order = 1
        - AddRequestHeader=name, ytr # order = 2
        - AddRequestHeader=name, zhn # order = 3

  • org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters(): ① 加载 DefaultFilter;② 加载路由过滤器;③ 合并 DefaultFilter 和路由过滤器
  • org.springframework.cloud.gateway.handler.FilteringWebHandler#handle(): ① 加载全局过滤器;② 与 DefaultFilter 和路由过滤器合并;③ 根据合并后的 order 值排序;④ 组织过滤器链

六、网关跨域

(1) 跨域

浏览器有个同源策略(Same-Origin Policy):默认情况下,AJAX 请求只能发送给同源的 URL

📚 AJAX:Asynchronous Javascript And XML【异步 JavaScript 和 XML】

  • 同源指 ① 协议、② 域名(IP)、③ 端口 相同
  • img、script、link、iframe、video、audio 等标签不受同源策略约束


跨域问题: 浏览器要求发送请求的来源和接收请求的接口的协议、域名和端口必须相同,否则该请求会被浏览器拦截


📚 CORS(Cross-Origin Resource Sharing):跨域资源共享

(2) 网关跨域处理

  • 要访问 http://localhost:10010/orders/getOrderById/101?authorization=admin 地址的资源
  • 发送请求的来源是 http://localhost:8082/#/pages/index/index

❌ 端口不相同(不符合浏览器的同源策略)

📚 跨域访问检查发送的是 OPTIONS 请求

📚 跨域访问检查有效期要合理

spring:
  cloud:
    gateway: # 网关相关配置
      globalcors: # 全局跨域处理
        add-to-simple-url-handler-mapping: true # 防止 options 请求被拦截
        cors-configurations:
          '[/**]': # 拦截全部路径
            allowedOrigins: # 允许跨域访问的来源
              - "http://localhost:8082"
            allowedMethods: # 允许跨域访问的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许跨域访问携带请求头信息
            allowCredentials: true # 允许跨域访问携带 cookie
            maxAge: 360000 # 本次跨域访问检查的有效期
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
相关文章
|
1月前
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
1月前
|
负载均衡 算法 Java
【SpringCloud(2)】微服务注册中心:Eureka、Zookeeper;CAP分析;服务注册与服务发现;单机/集群部署Eureka;连接注册中心
1. 什么是服务治理? SpringCloud封装了Netfix开发的Eureka模块来实现服务治理 在传统pc的远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册
232 0
|
1月前
|
算法 Java 微服务
【SpringCloud(1)】初识微服务架构:创建一个简单的微服务;java与Spring与微服务;初入RestTemplate
微服务架构是What?? 微服务架构是一种架构模式,它提出将单一应用程序划分为一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。 每个服务允许在其独立的进程中,服务于服务间采用轻量级的通信机制互相协作(通常是Http协议的RESTful API或RPC协议)。 每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据上下文,选择合适的语言、工具对其进行构建
435 126
|
1月前
|
API 微服务
阿里云微服务引擎 MSE 及 API 网关 2025 年 9 月产品动态
阿里云微服务引擎 MSE 及 API 网关 2025 年 9 月产品动态。
163 26
|
2月前
|
运维 Cloud Native 应用服务中间件
阿里云微服务引擎 MSE 及 API 网关 2025 年 9 月产品动态
阿里云微服务引擎 MSE 面向业界主流开源微服务项目, 提供注册配置中心和分布式协调(原生支持 Nacos/ZooKeeper/Eureka )、云原生网关(原生支持Higress/Nginx/Envoy,遵循Ingress标准)、微服务治理(原生支持 Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服务治理规范)能力。API 网关 (API Gateway),提供 APl 托管服务,覆盖设计、开发、测试、发布、售卖、运维监测、安全管控、下线等 API 生命周期阶段。帮助您快速构建以 API 为核心的系统架构.满足新技术引入、系统集成、业务中台等诸多场景需要。
454 142
|
2月前
|
监控 安全 Java
Spring Cloud 微服务治理技术详解与实践指南
本文档全面介绍 Spring Cloud 微服务治理框架的核心组件、架构设计和实践应用。作为 Spring 生态系统中构建分布式系统的标准工具箱,Spring Cloud 提供了一套完整的微服务解决方案,涵盖服务发现、配置管理、负载均衡、熔断器等关键功能。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
205 1
API 微服务
91 0
|
2月前
|
jenkins Java 持续交付
使用 Jenkins 和 Spring Cloud 自动化微服务部署
随着单体应用逐渐被微服务架构取代,企业对快速发布、可扩展性和高可用性的需求日益增长。Jenkins 作为领先的持续集成与部署工具,结合 Spring Cloud 提供的云原生解决方案,能够有效简化微服务的开发、测试与部署流程。本文介绍了如何通过 Jenkins 实现微服务的自动化构建与部署,并结合 Spring Cloud 的配置管理、服务发现等功能,打造高效、稳定的微服务交付流程。
408 0
使用 Jenkins 和 Spring Cloud 自动化微服务部署
|
2月前
|
Kubernetes Java 微服务
Spring Cloud 微服务架构技术解析与实践指南
本文档全面介绍 Spring Cloud 微服务架构的核心组件、设计理念和实现方案。作为构建分布式系统的综合工具箱,Spring Cloud 为微服务架构提供了服务发现、配置管理、负载均衡、熔断器等关键功能的标准化实现。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
419 0
|
3月前
|
运维 Cloud Native 应用服务中间件
阿里云微服务引擎 MSE 及 API 网关 2025 年 8 月产品动态
阿里云微服务引擎 MSE 面向业界主流开源微服务项目, 提供注册配置中心和分布式协调(原生支持 Nacos/ZooKeeper/Eureka )、云原生网关(原生支持Higress/Nginx/Envoy,遵循Ingress标准)、微服务治理(原生支持 Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服务治理规范)能力。API 网关 (API Gateway),提供 APl 托管服务,覆盖设计、开发、测试、发布、售卖、运维监测、安全管控、下线等 API 生命周期阶段。帮助您快速构建以 API 为核心的系统架构.满足新技术引入、系统集成、业务中台等诸多场景需要。
459 152