> 文章列表 > Spring Cloud Gateway: 网关

Spring Cloud Gateway: 网关

Spring Cloud Gateway: 网关

文章目录

  • 网关
  • Hello world
  • 路由: Route
    • 谓词: Predicate
    • 过滤器: Filter
      • Gateway实现限流: RequestRateLimiter过滤器
      • 使用Gateway实现服务降级
  • 自定义全局过滤器
  • GateWay中执行流程

网关

API网关就是实现了前端项目和服务端项目之间的统一入口
Nginx实现的是用户和前端项目之间调用的入口
Ribbon实现是后端服务之间相互调用的负载均衡算法
Spring Cloud Gateway: 网关

API网关作用就是把各个服务对外提供的API汇聚起来,让外界看起来是一个统一的接口。同时在网关中提供额外的功能。

Hello world

一.搭建Eureka Server
二.搭建application client集群
三.搭建Gateway网关微服务
1.导入依赖

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
</dependencies>

2.编写yml配置文件

server:port: 9999
eureka:client:service-url:defaultZone: http://localhost:8761/eureka/
spring:application:name: cloud-gatewaycloud: # spring cloud相关配置的常用前缀gateway: # 网关技术配置前缀discovery: # 自动发现工具locator: # 本地逻辑enabled: true # 开启自动发现工具的本地路由逻辑lower-case-service-id: true # 把从EurekaServer上发现的服务名称,转换成全小写,只要小写的服务名称才能访问,大写的不行!!!!!!

四.启动服务
自动发现工具的本地路由规则是:
请求路径 - http://网关IP:网关端口/微服务的服务名/要访问的具体地址
gateway自动解析,把请求地址中的’微服务的服务名’截取,从Eureka Client发现的服务列表中查看,如果有同名服务,则开始转发。
如: http://localhost(网关IP):9999(网关端口)/application(服务集群名)/save(具体访问地址)

路由: Route

一个路由包含ID、URI、Predicate集合、Filter集合。
在Route中ID是自定义,但唯一,URI就是一个地址。
谓词: 路由前的条件和内容.
Filter负责在路由后,代理服务“之前”或“之后”做的一些事情。

谓词: Predicate

对前端发来的请求进行校验
1.Path: 用于匹配路由地址规则的谓词。

spring:cloud: gateway:discovery:locator:enabled: false # 关闭自动发现工具的本地路由逻辑lower-case-service-id: true routes: - id: application-service # 路由的唯一名称,随便定义,不重复即可uri: lb://application-service # 规则满足后,转发到的地址。lb是spring cloud gateway支持的一种协议名predicates: Path=/edit # 谓词  路由地址规则  Path=/edit/** 代表所有访问url中代用edit的都可以走这个路由

2.Query: 校验请求url是否包含指定的请求参数及参数值是否符合要求,只能校验请求地址参数,也就是 /path?参数

方式一: 只能指定是否有指定请求参数,不能指定参数值
predicates: Path=/demo/**,Query=abc方式二: 常用,可以指定请求参数及参数值,但是不能指定参数值中带有","的参数值
predicates: - Path=/demo/**- Query=name,fs.* # 请求参数必须包含name,请求参数的值必须以 fs开头- Query=age,18 # 请求参数必须包含age方式三:
predicates: 可以指定请求参数值中带有","的参数值- Path=/demo02- name: Queryargs:param: abcregexp: 12,3

3.Header: 校验请求中是否包含指定的请求头及请求头数值是否符合要求
4.Method: 请求方式。支持多个值,使用逗号分隔
5.Cookie: 包含指定Cookie名和满足特定正则要求的值: Cookie参数值要是正则表达式
**

  predicates:- Path=/service/**  - Header=Host,.* # 请求头必须有Host,值为任意字符串- Header=abc,123 # 请求头中包含abc,且值为123- Method=GET,POST # 请求方式必须是GET或POST- Cookie=name,bjsxt.* # 请求必须包含名称是name,值符合bjsxt开头的cookie。

6.RemoteAddr: 允许访问的客户端IP

  predicates:- Path=/service/** - RemoteAddr=192.168.41.252 # 客户端IP必须是192.168.41.252

7.Host: 匹配请求中Host请求头的值。满足Ant模式(之前在Spring Security中学习过)可以使用:

  • ? 匹配一个字符
  • * 匹配0个或多个字符
  • ** 匹配0个或多个目录
  predicates:- Path=/service/** - Host=127.0.0.1:9999 # 请求头Host值必须是127.0.0.1:9999

8.时间限制:
下面三个一般只存在一个即可
Before: 在指定时间点之前
After: 在指定时间点之后。
Between: 请求时必须在设定的时间范围内,才进行路由转发。

  predicates:- Path=/service/** - Before=2022-10-01T18:00:00.000+08:00[Asia/Shanghai] # 2022-10-01晚18点前可以访问- After=2020-10-01T08:00:00.000+08:00[Asia/Shanghai] # 2020-10-01早8点后可以访问- Between=2020-10-01T08:00:00.000+08:00[Asia/Shanghai],2022-10-01T18:00:00.000+08:00[Asia/Shanghai] # 2020-10-01早8点后,2022-10-01晚18点前可以访问

9.Weight: 对服务名指定分组合权重
Weight=组名,负载均衡权重
例: 在Eureka中注册两个服务,这个服务(项目)是相同的,应用程序名分别叫做application-service1和application-service2。
Gateway在路由匹配时application-service1将占20%,application-service2将占80%。

- id: application-service1uri: lb://application-service1predicates:- Path=/service/**- Weight=group1,2
- id: application-service2uri: lb://application-service2predicates:- Path=/service/**- Weight=group1,8

过滤器: Filter

路由转发之后,被代理的服务执行前后运行的
路由过滤器:框架内置的Filter实现都是路由过滤器,都是GatewayFilter实现类型。
全局过滤器:框架未内置全局过滤器实现,需自定义。全局过滤器需实现接口GlobalFilter。

          filters: #/配置路由规则- stripPrefix=1 #跳过路径中的前几级发送给下游地址- AddRequestHeader=sxt,123 #给下游请求添加请求头- AddRequestParameter=abc,123 #给下游服务传递请求参数- AddResponseHeader=cou,javaEE #设置响应头- DedupeResponseHeader=cou,RETAIN_FIRST #当相应头重复后﹑保留第一个- SetPath=/{segment} #重新的设置路徭

Gateway实现限流: RequestRateLimiter过滤器

常见限流算法
一.计数器算法: 每个请求让计数器加一,当到达设定值后,其他的请求都拒绝。到下一秒开始时,计数清零,重新开始计数。
二.漏桶算法: 不论请求多少,都以恒定速度处理请求
三.令牌桶算法: 在桶中放令牌,请求获取令牌后才能继续执行,不论请求多少,执行速率都由生产令牌的速率控制.
令牌桶算法
1.导入依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.新建密钥解析器
注意这里使用IP解析

@Component
public class MyKeyResolver implements KeyResolver {@Overridepublic Mono<String> resolve(ServerWebExchange exchange) {String ip = exchange.getRequest() // 获取请求对象.getRemoteAddress() // 获取客户端地址对象 InetSocketAddress.getAddress() // 获取客户端地址对象 InetAddress.getHostAddress(); // 获取客户端的主机地址(IP或唯一的主机名)return Mono.just(ip); // 创建返回结果对象}
}

3.yml配置文件

          filters:- name: RequestRateLimiterargs:keyResolver: '#{@xxx}'redis-rate-limiter.replenishRate: 1 # 每秒令牌生成速率redis-rate-limiter.burstCapacity: 2 # 令牌桶容量上限

4.测试:
使用JMeter访问 http://localhost:9999/save 若干次,结果是,第一秒可处理2个请求(令牌桶上限),后续每秒可以处理1个请求(令牌生成速率)。

使用Gateway实现服务降级

1.导入依赖

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

2.在Gateway的controller创建托底方法

@RestController
public class MyController {@RequestMapping("/fallback")public String show(){return "托底方法";}
}

3.yml配置

          filters:- name: Hystrixargs:name: fallback # 随意定义的名称。相当于@HystrixCommand注解中的commandKey属性。# 如果转发的服务不可用,请求转发到当前Gateway模块映射路径为fallback(随意命名和映射路径一致即可)的控制单元上。fallbackUri: forward:/fallback 

自定义全局过滤器

/*** 自定义全局过滤器。* 必须实现接口GlobalFilter* 当前类型的对象,必须被spring容器管理。* 无须配置,所有路由都生效。** 执行顺序:*  先执行网关过滤器,后执行全局过滤器*  多个全局过滤器,执行顺序由Spring boot扫描管理当前对象的顺序决定。*  每个过滤器,都是完整执行后,才执行下一个过滤器。*/
@Component
public class MyGlobalFilter implements GlobalFilter {/*** 过滤方法。* 实现上,只有唯一的要求。必须调用方法chain.filter(exchange),并把方法的返回值,返回。* @param exchange* @param chain* @return*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {System.out.println("前置全局过滤");//放行/执行下一个过滤器Mono<Void> result = chain.filter(exchange);System.out.println("后置全局过滤");return result;}
}

GateWay中执行流程

1.网关客户端访问Gateway网关,Gateway中Handler Mapping对请求URL进行处理。
2.处理完成后,交由Web Handler处理,Web Handler 运行时会被Filter过滤。Filter中前半部分代码是处理请求的代码。
3/处理完成后调用真实被代理的服务;被代理服务返回响应结果,结果会被Filter中后半部分代码过滤处理;
4,操作完成后把结果返回给Web Hanlder,再返回给Handler Mapping,最终响应给客户端。

GateWay的底层: 底层框架是Netty(NIO) :对java.net中内容进行封装 【NIO】 AIO进行封装