Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。Spring Cloud Gateway作为Spring Cloud生态系中的网关,目标是替代ZUUL,其不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。
网关功能:
在SpringCloud中网关的实现包括两种:
搭建网关服务的步骤:
<dependencies>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
dependencies>
server:
port: 10010 #网关端口
spring:
application:
name: gateway #服务名称
cloud:
nacos:
server-addr: localhost:8848 #nacos地址
gateway:
routes: #网关路由配置
- id: user-service # 路由id,自定义,唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址,http就是固定地址
uri: lb://userservice # 路由的目标地址,lb代表负载均衡
predicates: # 路由断言,判断请求是否符合规则
- Path=/user/** #路径断言,判断路径是否以/user开头,如果是则符合
- id: order-service
uri: lb://orderservice
predicates:
- Path=/order/**
Route Predicate Factory 作用是读取用户定义的断言条件,对请求做出判断。
网关路由可以配置的内容包括:
我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件。
例如Path=/user/**是按照路径匹配,这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的,像这样的断言工厂在SpringCloudGateway还有十几个,可以在spring官网查看用法。
Spring提供了11种基本的Predicate工厂:
GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理。
Spring提供了31种不同的路由过滤器工厂。例如:
例如:给所有进入userservice的请求添加一个请求头:Truth=itcast is freaking awesome!
实现方式:在gateway中修改application.yml文件,给userservice的路由添加过滤器:
spring:
application:
name: gateway #服务名称
cloud:
nacos:
server-addr: localhost:8848 #nacos地址
gateway:
routes: #网关路由配置
- id: user-service # 路由id,自定义,唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址,http就是固定地址
uri: lb://userservice # 路由的目标地址,lb代表负载均衡
predicates: # 路由断言,判断请求是否符合规则
- Path=/user/** #路径断言,判断路径是否以/user开头,如果是则符合
filters: # 过滤器
- AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头
如果要对所有的路由都生效,则可以将过滤器工厂写到default下。格式如下:
spring:
application:
name: gateway #服务名称
cloud:
nacos:
server-addr: localhost:8848 #nacos地址
gateway:
routes: #网关路由配置
- id: user-service # 路由id,自定义,唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址,http就是固定地址
uri: lb://userservice # 路由的目标地址,lb代表负载均衡
predicates: # 路由断言,判断请求是否符合规则
- Path=/user/** #路径断言,判断路径是否以/user开头,如果是则符合
# filters: # 过滤器
# - AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头
- id: order-service
uri: lb://orderservice
predicates:
- Path=/order/**
default-filters: # 默认过滤器,会对所有的路由请求都生效
- AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头
全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。
区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。
定义方式是实现GlobalFilter接口。
public interface GlobalFilter {
/**
* 处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
*
* @param exchange 请求上下文,里面可以获取Request、Response等信息
* @param chain 用来把请求委托给下一个过滤器
* @return {@code Mono} 返回标示当前过滤器业务结束
*/
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
这里实现一个定义全局过滤器,拦截并判断用户身份的案例:
需求:定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:
步骤1:自定义过滤器:
自定义类,实现GlobalFilter接口,添加@Order注解:
@Order(-1) //优先级
@Component
public class AuthorizeFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//1、获取请求参数
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> params = request.getQueryParams();
//2、获取authorization参数
String authorization = params.getFirst("authorization");
//3、校验
if("admin".equals(authorization)){
//放行
return chain.filter(exchange);
}
//4、拦截
//4.1禁止访问
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
//4.2结束处理
return exchange.getResponse().setComplete();
}
}
1.全局过滤器的作用是什么?
对所有路由都生效的过滤器,并且可以自定义处理逻辑。
2.实现全局过滤器的步骤?
请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter。
请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器。
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()方法是先加载defaultFilters,然后再加载某个route的filters,然后合并。
org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()方法会加载全局过滤器,与前面的过滤器合并后根据order排序,组织过滤器链。
跨域:域名不一致就是跨域,主要包括:
网关处理跨域采用的同样是CORS方案,并且只需要简单配置即可实现:
spring:
cloud:
gateway:
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
corsConfigurations:
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求
- "http://localhost:63343"
- "http://www.leyou.com"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期
再次查看,就没有跨域问题了。
限流:对应用服务器的请求做限制,避免因过多请求而导致服务器过载甚至宕机。限流算法常见的包括两种:
计数器算法:
固定窗口计数器算法概念如下:
漏桶算法:
令牌桶算法: