SpringCloudAlibaba之gateway网关

本文介绍Spring Cloud Gateway的搭建过程、工作原理及高级特性,包括路由配置、断言工厂、过滤器配置等内容,并提供了详细的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. Gateway

1.1. 什么是网关

1.1.1. 网关的功能
  1. 身份认证
  2. 权限校验
  3. 服务路由
  4. 负载均衡
  5. 请求限流
1.1.2. Spring Cloud网关落地方案
  1. Zuul是基于Servlet实现的,属于阻塞式编程
  2. Gateway是基于Spring5中提供的 spring-webflux 实现的,属于响应式编程,性能要由于Zuul

1.2. 搭建网关服务

1.2.1. 创建一个gateway-service服务

引入gateway的依赖:spring-cloud-starter-gateway不需要spring-boot-starter-web;如果他们同时存在则gateway不可用。故我们需要把父工程中的spring-boot-starter-web排除,其它子模块重新引入web包即可。

<?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">
    <parent>
        <artifactId>cloud-demo</artifactId>
        <groupId>com.acx</groupId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.acx</groupId>
    <artifactId>gateway-service</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <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>

</project>
1.2.2. 编写网关配置
server:
  port: 10010
spring:
  application:
    name: gateway-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        cluster-name: HZ
    gateway:
      routes:
        - id: order-service # 自定义路由id,必须唯一
          uri: lb://order-service # lb是负载均衡(默认是轮询)的意思,后面跟的是服务名称
          predicates:
            - Path=/order/**,/order/api/** # 这是路由断言;只要是以/orderservice或者/orderservice/api开头的请求就会被路由到order-service服务上
        - id: product-service # 商品服务路由id
          uri: lb://product-service
          predicates:
            - Path=/product/**,/product/api/**
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/user/**,/user/api/**
1.2.3. 测试网关是否生效
  • 访问http://localhost:10010/order/getOne

在这里插入图片描述

2. Gateway原理

2.1. 网关处理流程

在这里插入图片描述

2.2. 断言工厂(PathRoutePredicateFactory)

作用:读取断言规则并处理,转变为路由判断的条件,最后规则由PathRoutePredicateFactory断言工厂处理。

11种断言工厂

断言工厂说明
After某个时间点之后请求
Before某个时间点之前请求
Between某两个时间点之间请求
Cookie请求必须包含某些cookie
Header请求必须包含某些header
Host请求必须是指定方式
Method请求必须是指定方法:GET、POST
Path(默认)请求路径必须是指定路由规则
Query请求必须包含指定参数
RemoteAddr请求这IP必须为指定范围
Weight权重处理

11种断言示例:具体的示例可以查询官网文档https://www.springcloud.cc/spring-cloud-greenwich.html#gateway-request-predicates-factories

# After
predicates:
  - After=2022-01-20T17:42:47.789-07:00[America/Denver]    
  
# Before
predicates:       
  - Before=2017-01-20T17:42:47.789-07:00[America/Denver]   
  
# Between
predicates:
  - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver] 
  
# Cookie
predicates:
  - Cookie=chocolate, ch.p   # 使用Cookie路由断言工厂,配置cookie,正则表达式(可有可无)
  
# Header
predicates:
  - Header=X-Request-Id, \d+
  
# Host   
predicates:
  - Host=**.somehost.org,**.anotherhost.org
  
# Method
predicates:
  - Method=GET,POST
  
# Query
predicates:
  - Query=green
  
# RemoteAddr
predicates:
  - RemoteAddr=192.168.1.1/24
  
#   Weight
predicates:
  - Weight=group1, 2

2.3. 路由过滤器配置(GatewayFilter)

2.3.1. 请求过滤器流程图

作用:过滤器链对进入网关的请求和微服务返回的响应做处理
在这里插入图片描述

2.3.2. 过滤器工厂

Spring Cloud Gateway官网实例:https://www.springcloud.cc/spring-cloud-greenwich.html#_addrequestheader_gatewayfilter_factory

常用的过滤器工厂

过滤器工厂作用参数
AddRequestHeader为原始请求添加HeaderHeader的名称及值
AddRequestParameter为原始请求添加请求参数参数名称及值
AddResponseHeader为原始响应添加HeaderHeader的名称及值
DedupeResponseHeader剔除响应头中重复的值需要去重的Header名称及去重策略
Hystrix为路由引入Hystrix的断路器保护HystrixCommand的名称
2.3.3. 局部配置过滤器

已AddRequestHeader拦截器为例

网关服务做如下配置

server:
  port: 10010
spring:
  application:
    name: gateway-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        cluster-name: HZ
    gateway:
      routes:
        - id: order-service # 自定义路由id,必须唯一
          uri: lb://order-service # lb是负载均衡(默认是轮询)的意思,后面跟的是服务名称
          predicates:
            - Path=/order/**,/order/api/** # 这是路由断言;只要是以/orderservice或者/orderservice/api开头的请求就会被路由到order-service服务上
          filters:
            - AddRequestHeader=abc,hello word # 给order服务配置拦截器
        - id: product-service # 商品服务路由id
          uri: lb://product-service
          predicates:
            - Path=/product/**,/product/api/**
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/user/**,/user/api/**

Order服务添加获取abc请求头代码

package com.acx.controller;

import com.acx.client.UserClient;
import com.acx.pojo.vo.ActorInfoVO;
import com.acx.pojo.vo.OrderInfoVO;
import com.acx.pojo.vo.StudentVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("order")
public class OrderController {

    private static final Logger logger = LoggerFactory.getLogger(OrderController.class);

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private UserClient userClient;

    @Autowired
    private StudentVO studentVO;

    @GetMapping("getStudent")
    public StudentVO getStudent() {
        return studentVO;
    }

    @GetMapping("getOne")
    public OrderInfoVO getOne(@RequestHeader("abc") String abc) {
        logger.info("开始查询订单");
        OrderInfoVO orderInfoVO = new OrderInfoVO();
        orderInfoVO.setOrderName("订单123");
        orderInfoVO.setOrderSn("046b399937ad4271bcd5ed275f2b4682");
        orderInfoVO.setProductName("商品123");
        orderInfoVO.setProductNum(23);
        int userId = 1;
//        String getUserUrl = "http://127.0.0.1:8083/user/getUser/" + userId;
//        String getUserUrl = "http://user-service/user/getUser/" + userId;
        //服务发现
//        ActorInfoVO actor = restTemplate.getForObject(getUserUrl, ActorInfoVO.class);
        ActorInfoVO actor = userClient.getUser(userId);
        orderInfoVO.setUser(actor);
        logger.info("测试AddRequestHeader拦截器是否生效,abc={}", abc);
        return orderInfoVO;
    }

}

请求Order接口测试:http://localhost:10010/order/getOne

  • 控制台打印日志如下:说明过滤器生效了
2022-05-09 22:41:58.698  INFO 19452 --- [nio-8081-exec-1] com.acx.controller.OrderController       : 测试AddRequestHeader拦截器是否生效,abc=hello word

2.4. 全局默认过滤器(DefaultFilter)

  • 所有经过此网关路由的服务器请求都会对此过滤器生效
server:
  port: 10010
spring:
  application:
    name: gateway-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        cluster-name: HZ
    gateway:
      routes:
        - id: order-service # 自定义路由id,必须唯一
          uri: lb://order-service # lb是负载均衡(默认是轮询)的意思,后面跟的是服务名称
          predicates:
            - Path=/order/**,/order/api/** # 这是路由断言;只要是以/orderservice或者/orderservice/api开头的请求就会被路由到order-service服务上
        - id: product-service # 商品服务路由id
          uri: lb://product-service
          predicates:
            - Path=/product/**,/product/api/**
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/user/**,/user/api/**
      default-filters:
        - AddRequestHeader=abc,hello word # 全局配置拦截器

2.5. 全局过滤器(GlobalFilter)

2.5.1. 什么是全局过滤器

作用:处理一切进入网关服务的请求和响应,与GatewayFilter作用一样,区别在于GlobalFilter支持自定义逻辑扩展。

核心方法:

public interface GlobalFilter {

	/**
	 * Process the Web request and (optionally) delegate to the next {@code WebFilter}
	 * through the given {@link GatewayFilterChain}.
	 * @param exchange the current server exchange
	 * exchange: 请求上下文,里面包含了Request、Response等信息
	 * @param chain provides a way to delegate to the next filter
	 * chain: 用来把请求委托给下一个过滤器
	 * @return {@code Mono<Void>} to indicate when request processing is complete
	 * MonoZ: 返回时表示当前过滤器逻辑流程结束
	 */
	Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);

}
2.5.2. 应用:自定义一个登陆验证拦截器

Gateway网关服务:自定义认证拦截器,此拦截器集成GlobalFilter

package com.acx.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Order(1) //拦截器优先级;值越小优先级越高
@Component
public class AuthFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.获取request
        ServerHttpRequest request = exchange.getRequest();
        //2.获取请求参数
        MultiValueMap<String, String> params = request.getQueryParams();
        //3.获取token
        String token = params.getFirst("token");
        if ("login".equals(token)) {
            //4.是、请求通过
            return chain.filter(exchange);
        }
        //5.否、校验未通过
        //5.1.设置校验未通过code 401 认证未通过
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }

}

测试结果:认证失败

在这里插入图片描述

测试结果:认证成功

在这里插入图片描述

2.5. 过滤器执行顺序


前言:请求到达网关服务后,一共要经过路由过滤器、DefaultFilter、GlobalFilter三种过滤器组成的过滤器链。他们会有一个执行顺序,排序后一次执行每个过滤器。

规则

  1. 当Order值一样时DefaultFilter > 路由过滤器 > GlobalFilter。
  2. Order值越小、Filter优先级越高。

Order值

  1. GlobalFilter的order值可以自己进行指定。
  2. DefaultFilter和路由过滤器的Order值是由Spring决定的,默认按照声明顺序从1递增。

实例如下:

server:
  port: 10010
spring:
  application:
    name: gateway-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        cluster-name: HZ
    gateway:
      routes:
        - id: order-service # 自定义路由id,必须唯一
          uri: lb://order-service # lb是负载均衡(默认是轮询)的意思,后面跟的是服务名称
          predicates:
            - Path=/order/**,/order/api/** # 这是路由断言;只要是以/orderservice或者/orderservice/api开头的请求就会被路由到order-service服务上
          filters:
            - AddRequestHeader=zhangsan,abc123 # order = 1,越往后Order值就越大
        - id: product-service # 商品服务路由id
          uri: lb://product-service
          predicates:
            - Path=/product/**,/product/api/**
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/user/**,/user/api/**
      default-filters:
        - AddRequestHeader=abc,hello word # 全局配置拦截器;order=1,越往后Order值就越大


2.6. 网关的跨域问题处理

2.6.1. 什么是跨域问题

浏览器禁止请求发送者与服务端发生卡与Ajax请求;请求域名或者端口与后台目标域名地址不一样时就会出现这种问题。

例子:下面的情况就会出现cors跨域问题

  1. 游览器请求地址:127.0.0.1:8080
  2. 目标后台地址:127.0.0.1:10100
2.6.2. 配置文件解救跨域问题
spring:
  cloud:
    gateway:
      # 允许跨域请求配置
      globalcors:
        cors-configurations:
          '[/**]':
            # 允许任何域名使用
            allowedOrigins: "*"
            # 允许任何头
            allowedHeaders: "*"
            # 允许任何方法(post、get等)
            allowedMethods: "*"
            # sessionid 多次访问一致
            allowCredentials: true
        # 允许来自所有域名(allowedOrigins)的所有请求方式(allowedMethods)发出CORS请求
        add-to-simple-url-handler-mapping: true   # 允许来自所有域名(allowedOrigins)的所有请求方式(allowedMethods)发出CORS请求7

2.6.3. 代码解决跨域问题
@Configuration
public class CorsConfig {
  
  @Bean
  public CorsWebFilter corsFilter() {
    CorsConfiguration corsConfiguration = new CorsConfiguration();
    // 允许任何域名使用
    corsConfiguration.addAllowedOrigin("*");
    // 允许任何头
    corsConfiguration.addAllowedHeader("*");
    // 允许任何方法(post、get等)
    corsConfiguration.addAllowedMethod("*");

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
      
    source.registerCorsConfiguration("/**", corsConfiguration);

    return new CorsWebFilter(source);
  }
}

<think>嗯,用户问的是关于Spring Cloud Alibaba整合Gateway的介绍。首先,我需要确定用户对这两个组件的了解程度。可能他们有一定的Spring Cloud基础,但可能不太清楚如何将Spring Cloud AlibabaGateway结合起来使用。所以,我需要先简要介绍这两个组件,然后说明整合的必要性和步骤。 首先,Spring Cloud Alibaba是阿里巴巴提供的微服务解决方案,包含Nacos、Sentinel等组件,用于服务发现、配置管理、限流等。而Spring Cloud GatewaySpring官方提供的API网关,负责路由、过滤、负载均衡等。整合它们可以构建一个完整的微服务架构。 接下来,用户可能需要具体的整合步骤。我应该分步骤说明,比如创建项目、添加依赖、配置Nacos和Gateway的路由规则,以及如何集成Sentinel进行限流。要注意依赖版本之间的兼容性,比如Spring Boot、Spring Cloud和Spring Cloud Alibaba的版本对应,这是容易出错的地方,需要提醒用户注意。 然后,考虑用户可能的实际应用场景,比如动态路由配置,这时候需要提到Nacos作为配置中心,动态更新路由规则。另外,整合Sentinel做网关限流也是一个常见需求,应该给出示例配置。 还要注意可能的常见问题,比如依赖冲突、配置错误等,可以给出一些排查建议,比如检查版本是否匹配,配置文件是否正确,以及如何通过日志调试。 用户可能有不同的使用场景,比如是否需要服务注册发现,或者只是用配置中心。因此,在整合步骤中需要明确说明如何注册到Nacos,并确保服务发现的功能正常。 最后,是否需要代码示例?可能需要提供一个简单的application.yml配置示例,说明路由规则和Nacos的配置,以及Sentinel的集成部分。这样用户可以直接参考示例进行配置,减少出错的可能。 总结下来,回答的结构应该是先介绍两者,再说明整合的好处,然后详细步骤,包括依赖配置、路由设置、动态配置和限流整合,最后给出注意事项和常见问题解决方法。同时,确保语言简洁明了,避免过于技术化的术语,让不同层次的用户都能理解。</think>Spring Cloud AlibabaSpring Cloud Gateway 整合可以构建一个功能完善的微服务网关,结合阿里巴巴生态组件(如 Nacos、Sentinel)实现动态路由、流量控制和服务治理。以下是整合的核心要点和步骤: --- ### **1. 核心组件作用** - **Spring Cloud Gateway**:API 网关,负责路由转发、鉴权、限流、熔断等。 - **Nacos**:服务注册与配置中心,实现服务发现和动态路由配置。 - **Sentinel**:流量控制与熔断降级,保护网关和后端服务。 --- ### **2. 整合步骤** #### **2.1 创建项目并添加依赖** 在 `pom.xml` 中添加关键依赖: ```xml <!-- Spring Cloud Alibaba 基础依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!-- Spring Cloud Gateway --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> ``` #### **2.2 配置文件(application.yml)** 配置 Nacos 服务发现和 Gateway 路由: ```yaml server: port: 8080 spring: application: name: api-gateway cloud: nacos: discovery: server-addr: localhost:8848 # Nacos 地址 gateway: discovery: locator: enabled: true # 开启服务发现路由 routes: - id: user-service uri: lb://user-service # 负载均衡到 user-service predicates: - Path=/user/** # 匹配路径 filters: - StripPrefix=1 # 去掉前缀 /user sentinel: transport: dashboard: localhost:8080 # Sentinel 控制台地址 ``` --- ### **3. 动态路由与 Nacos 整合** 通过 Nacos 配置中心动态更新路由规则: 1. 在 Nacos 控制台创建 `Data ID` 为 `gateway-routes.json` 的配置文件。 2. 配置内容示例: ```json [ { "id": "order-service", "predicates": [{"name": "Path", "args": {"pattern": "/order/**"}}], "filters": [{"name": "StripPrefix", "args": {"parts": 1}}], "uri": "lb://order-service", "order": 0 } ] ``` 3. 在 Gateway 中启用 Nacos 动态路由: ```java @Bean public NacosRouteDefinitionRepository nacosRouteDefinitionRepository() { return new NacosRouteDefinitionRepository(); } ``` --- ### **4. 整合 Sentinel 实现网关限流** 配置 Sentinel 对网关流量进行控制: 1. **添加依赖**: ```xml <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId> </dependency> ``` 2. **在 Sentinel 控制台配置流控规则**: - 针对路由 ID(如 `user-service`)设置 QPS 阈值。 3. **自定义限流异常响应**: ```java @Bean public GatewayCallbackManager sentinelGatewayCallbackManager() { GatewayCallbackManager.setBlockHandler((exchange, ex) -> { return ServerResponse.status(429) .body(BodyInserters.fromValue("Too many requests!")); }); return new GatewayCallbackManager(); } ``` --- ### **5. 注意事项** 1. **版本兼容性**:确保 Spring Boot、Spring Cloud 和 Spring Cloud Alibaba 版本匹配(例如:Spring Boot 2.6.x + Spring Cloud 2021.x + Spring Cloud Alibaba 2021.0.5.0)。 2. **路由优先级**:通过 `order` 字段控制路由匹配顺序。 3. **过滤器链**:可自定义全局过滤器(GlobalFilter)实现鉴权、日志等逻辑。 --- ### **6. 总结** 通过整合 Spring Cloud AlibabaGateway,可以实现: - **动态路由**:基于 Nacos 实时更新路由规则。 - **流量治理**:通过 Sentinel 实现网关级限流和熔断。 - **服务发现**:自动发现后端微服务实例。 此方案适合需要高可用、动态扩展的微服务架构,典型场景如电商秒杀、API 开放平台等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值