文章目录
- 网关
- Hello world
- 路由: Route
- 谓词: Predicate
- 过滤器: Filter
- Gateway实现限流: RequestRateLimiter过滤器
- 使用Gateway实现服务降级
- 自定义全局过滤器
- GateWay中执行流程
网关
API网关就是实现了前端项目和服务端项目之间的统一入口
Nginx实现的是用户和前端项目之间调用的入口
Ribbon实现是后端服务之间相互调用的负载均衡算法
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-gateway
cloud: # 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: Query
args:
param: abc
regexp: 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-service1
uri: lb://application-service1
predicates:
- Path=/service/**
- Weight=group1,2
- id: application-service2
uri: lb://application-service2
predicates:
- 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 {
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
String ip = exchange.getRequest() // 获取请求对象
.getRemoteAddress() // 获取客户端地址对象 InetSocketAddress
.getAddress() // 获取客户端地址对象 InetAddress
.getHostAddress(); // 获取客户端的主机地址(IP或唯一的主机名)
return Mono.just(ip); // 创建返回结果对象
}
}
3.yml配置文件
filters:
- name: RequestRateLimiter
args:
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: Hystrix
args:
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
*/
@Override
public 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进行封装