概述

Spring Cloud Gateway使用了WebFlux技术,而WebFlux技术底层又基于高性能的Reactor模式通信框架Netty。Spring Cloud Gateway基于Spring 5、Spring Boot 2和project Reactor技术上构建异步非阻塞的高吞吐量API网关,提供一种简单且有效的方式来路由到API,并为它们提供横切关注点如安全性、监控/指标和弹性等。Spring Cloud Gateway特性如下:

Spring Cloud Gateway特性如下:

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(1)

网关作为系统的唯一流量入口,封装内部系统的架构,所有请求都先经过网关,由网关将请求路由到合适的微服务,优势如下:

流量网关与微服务网关

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(2)

流量网关(如典型Nginx网关)是指提供全局性的、与后端业务应用无关的策略,例如 HTTPS证书卸载、Web防火墙、全局流量监控等。而微服务网关(如Spring Cloud Gateway)是指与业务紧耦合的、提供单个业务域级别的策略,如服务治理、身份认证等。也就是说,流量网关负责南北向流量调度及安全防护,微服务网关负责东西向流量调度及服务治理。

主流网关

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(3)

从发展趋势上看,Spring Cloud Gateway作为Spring Cloud生态体系中的网关,目标替代Netflix的Zuul且势在必行。

术语

进一步研究 Spring Cloud Gateway 的配置及其使用之前,我们先了解几个 Spring Cloud Gateway 的核心术语

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(4)

工作流程

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(5)

实战加依赖

项目或模块中加入spring-cloud-starter-gateway

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>

如果引入了启动器,但又不希望启用网关,则可以通过设置spring.cloud.gateway.enabled=false来禁用。全部详细配置可以查阅官网, Spring Cloud Gateway详细配置说明 https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/appendix.html

官网提供两种配置谓词和过滤器的方法,分别是shortcuts and fully expanded arguments,译为快捷方式和完全扩展的参数方式,后续例子我们都使用快捷方式,这种方式简洁舒畅,官方的例子也大都是使用快捷方式。

路由配置Route 主要由路由id、目标uri、断言集合和过滤器集合组成

网关路由初体验

利用前面库存微服务提供的deduct接口,端口为4080,启动库存微服务,访问http://localhost:4080/deduct,显示成功

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(6)

创建网关微服务模块,pom文件依赖如下,由于后面我们有Gateway整合Nacos和Sentinel的示例,所以这里把其他依赖也先加进来

<?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>simple-ecommerce</artifactId> <groupId>cn.itxs</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>ecom-gateway</artifactId> <packaging>jar</packaging> <version>1.0</version> <name>ecom-gateway</name> <description>a simple electronic commerce platform demo tutorial for gateway service</description> <properties> <spring-cloud-loadbalancer.version>3.1.3</spring-cloud-loadbalancer.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId> <version>${spring-cloud-loadbalancer.version}</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <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> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> </dependencies> </project>

bootstrap.yml配置文件加入建议路由配置如下

server: port: 4090 spring: application: name: ecom-gateway cloud: gateway: routes: - id: storage_route uri: http://localhost:4080 predicates: - Path=/storage-service/** filters: - StripPrefix=1

启动网关微服务

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(7)

访问网关提供api接口http://localhost:4090/storage-service/deduct,匹配storage-service为真后通过过滤器去掉一层也即是storage-service路径去掉,然后转发至uri地址,最终转发url为http://localhost:4080/deduct ,成功返回结果

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(8)

整合Nacos

本地配置文件bootstrap.yml改为如下,commons-dev.yaml包含服务注册的组

spring: application: name: ecom-gateway profiles: active: dev cloud: nacos: # 注册中心信息放在配置中心上,每个程序一般只配置配置中心的信息 server-addr: 192.168.50.95:8848 config: server-addr: ${spring.cloud.nacos.server-addr} file-extension: yaml namespace: a2b1a5b7-d0bc-48e8-ab65-04695e61db01 group: gateway-group extension-configs: - dataId: commons-dev.yaml group: commons-group refresh: true username: itsx password: itxs123 enabled: true # 默认为true,设置false 来完全关闭 Spring Cloud Nacos Config refresh-enabled: true # 默认为true,当变更配置时,应用程序中能够获取到最新的值,设置false来关闭动态刷新,我们使用注册中心场景大部分就是动态感知,因此基本使用默认的

将路由配置也一并放在Nacos中配置ecom-gateway-dev.yaml,内容如下,uri这里使用的是库存微服务名称,lb是做负载均衡处理

server: port: 4090 spring: cloud: gateway: routes: - id: storage_route uri: lb://ecom-storage-service predicates: - Path=/storage-service/** filters: - StripPrefix=1

Nacos中commons-dev.yaml的关于Nacos注册中心使用配置如下,库存微服务也是使用这个,服务注册和发现都在ecom-group组

spring: cloud: nacos: discovery: server-addr: ${spring.cloud.nacos.server-addr} group: ecom-group namespace: a2b1a5b7-d0bc-48e8-ab65-04695e61db01 username: itsx password: itxs123

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(9)

启动库存微服务和网关微服务,都注册到同一个组里面

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(10)

再次访问http://localhost:4090/storage-service/deduct ,正常返回结果,到此我们已经成功整合Nacos

路由断言工厂

Route Predicate Factories为路由断言工厂,官网提供12种路由工厂,如果都没有满足你的需求,还可以自定义路由断言工厂

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(11)

我们先配置一个未来时间的after断言- After=2022-07-09T23:42:47.789-08:00[Asia/Shanghai]

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(12)

可以直接访问本机IP,返回一个错误的页面

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(13)

将after断言改为- Before=2022-07-09T23:42:47.789-08:00[Asia/Shanghai]后则可以正常访问。

自定义路由断言工厂

当官方提供的所有断言工厂无法满足业务需求时,还可以自定义断言工厂。添加自定义断言工厂类自定断言工厂主要注意一下几点:

新建一个库存数量的路由断言工厂QuantityRoutePredicateFactory.java,如库存在100和200之间可以访问

package cn.itxs.ecom.gateway.factory; import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; import org.springframework.stereotype.Component; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; import org.springframework.validation.annotation.Validated; import org.springframework.web.server.ServerWebExchange; import java.util.Arrays; import java.util.List; import java.util.function.Consumer; import java.util.function.Predicate; // 自定义路由断言工厂 @Component public class QuantityRoutePredicateFactory extends AbstractRoutePredicateFactory<QuantityRoutePredicateFactory.Config>{ public QuantityRoutePredicateFactory() { super(QuantityRoutePredicateFactory.Config.class); } // 将配置文件中的值按返回集合的顺序,赋值给配置类 @Override public List<String> shortcutFieldOrder() { return Arrays.asList(new String[]{"minQuantity", "maxQuantity"}); } @Override public Predicate<ServerWebExchange> apply(Consumer<Config> consumer) { return super.apply(consumer); } @Override public Predicate<ServerWebExchange> apply(Config config) { // 创建网关断言对象 // 检查 return serverWebExchange -> { // TODO 获取请求参数age,判断是否满足如配置的[100, 200) MultiValueMap<String, String> queryParams = serverWebExchange.getRequest().getQueryParams(); String quantity = queryParams.getFirst("quantity"); if (StringUtils.hasText(quantity) && quantity.matches("[0-9] ")) { int iQuantity = Integer.parseInt(quantity); if (iQuantity >= config.getMinQuantity() && iQuantity < config.getMaxQuantity()) { return true; } } return false; }; } // 配置类,属性用于接收配置文件中的值 @Validated public static class Config { private int minQuantity; private int maxQuantity; public int getMinQuantity() { return minQuantity; } public void setMinQuantity(int minQuantity) { this.minQuantity = minQuantity; } public int getMaxQuantity() { return maxQuantity; } public void setMaxQuantity(int maxQuantity) { this.maxQuantity = maxQuantity; } } }

Nacos网关的配置中增加自定义路由断言工厂配置Quantity

server: port: 4090 spring: cloud: gateway: routes: - id: storage_route uri: lb://ecom-storage-service predicates: - Path=/storage-service/** - Quantity=100,200 filters: - StripPrefix=1

启动网关微服务,访问http://localhost:4090/storage-service/deduct?quantity=99 ,没有匹配路由策略

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(14)

而访问http://localhost:4090/storage-service/deduct?quantity=100 ,能够正确返回库存微服务接口结果

springcloud gateway 配置说明(Gateway微服务网关实战与源码分析)(15)

,