目录
spring cloud中网关的实现有两种:
- Gateway
- zuul
Zuul是基于servlet的实现,属于阻塞式编程,而Gateway是基于视频日工5中提供的webflux,属于响应式编程的实现,具备更好的性能
Gateway的功能:
- 身份认证和权限校验服务
- 路由、负载均衡
- 请求限流
路由配置的几个概念:
- 路由id:路由的唯一标识
- URI:路由的目标地址,可以是lb根据服务名负载均衡或者是http为代表的固定地址
- predicates:路由断言,判断路由的规则
- filters:过滤器,对进入网关的请求和微服务返回的响应作处理
gateway搭建:
1.到入gateway坐标
<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>
2.编辑路由配置:
spring:
application:
name: gateway
cloud:
nacos:
server-addr: localhost:8848
gateway:
routes: #网关路由配置
- id: user_service #自定义路由id,唯一标识
# uri: http://localhost:8081 #路由到某个固定的http地址
uri: lb://userservice #路由的目标地址是lb负载均衡,后面跟服务名称
predicates: #路由断言,判断请求是否符合路由规则,符合规则才会路由
- Path=/user/** #按照路径匹配,只要以user开头的路径才路由
- After=2023-01-01T00:00:00.433+08:00[Asia/Shanghai]
路由断言工厂Route Predicate Factory
我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理
转变为路由判断的条件
例如Path=xx/xx,是按照路径匹配,这个规则是由
org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的
springcloudGateway中有十几种断言工厂:
例:
spring:
application:
name: gateway
cloud:
gateway:
routes: #网关路由配置
- id: user_service #自定义路由id,唯一标识
# uri: http://localhost:8081 #路由到某个固定的http地址
uri: lb://userservice #路由的目标地址是lb负载均衡,后面跟服务名称
predicates: #路由断言,判断请求是否符合路由规则,符合规则才会路由
- Path=/user/** #按照路径匹配,只要以user开头的路径才路由
过滤器(filters)
请求进入网关后先会去做路由,而断言工厂会根据路由规则去判断到底到达哪一个微服务,但路由之后并不是立即向微服务发起请求而是要通过一层一层的过滤器(过滤器链)之后才会向微服务发起请求,在这之间过滤器会对进入网关的请求做各种处理,比如:对请求头,请求体做各种处理,随后服务在得到请求后会做出响应,响应的结果也会经过过滤器的层层处理最终反馈给用户。而在这之间过滤器会对响应的结果做各种处理,比如:对响应头,请求体做各种处理。
spring中提供了三十多种过滤器工厂:
当前路由过滤器
设置在routes下面的只针对当前路由id生效
例:
spring:
application:
name: gateway
cloud:
gateway:
routes:
- id: user_service
uri: lb://userservice
predicates:
- Path=/user/**
filters: #过滤器
- AddRequestHeader=Point, this is request header! #添加请求头
默认过滤器(DefaultFilter)
上面的方式只能对单个路由生效,如果需要所有路由都添加某个过滤器,可以使用spring.cloud.gateway.default-filters设置为默认过滤器,此时所有的路由都会生效
例:
spring:
application:
name: gateway
cloud:
nacos:
server-addr: localhost:8848
gateway:
routes:
- id: user_service
uri: lb://userservice
predicates:
- Path=/user/**
- id: order_service
uri: lb://orderservice
predicates:
- Path=/order/**
#按照时间匹配:After:在莫个时间以后
- After=2023-01-01T00:00:00.433+08:00[Asia/Shanghai]
default-filters: #默认过滤器
- AddRequestHeader=Point, this is default filters! #添加请求头
使用@RequestHeader注解获取请求头打印结果
全局过滤器(GlobalFilter)
全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与默认过滤器的作用一样。
前两种是通过配置的方式设置的,处理逻辑是写死的,而GlobalFilter是需要自己写代码实现。
因此对于复杂的业务逻辑更加的灵活
实现方式是实现GlobalFilter接口:
我们通过模拟一个判断用户身份是否为admin的需求来进行配置:
需求:定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:参数中是否有authorization,
authorization参数值是否为admin如果同时满足则放行,否则拦截
//@Order(0)//设置拦截器的执行顺序,或者实现Ordered的接口
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//获取请求参数
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> queryParams = request.getQueryParams();
//获取参数中的 xx 参数
String authorization = queryParams.getFirst("authorization");
//如果没有这个参数便拦截
if (authorization == null) {
//不相等设置响应状态码。这里要的HttpStatus枚举
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
//拦截
return exchange.getResponse().setComplete();
}
//判断 xx 参数值是否相等
if (!(authorization.equals("admin"))) {
//不相等设置响应状态码
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
//拦截
return exchange.getResponse().setComplete();
}
//放行
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
当我输入http:localhost:10010/user/1时
当我输入http:/llocalhost:10010/user/1?authorization=account时
当我输入http:/llocalhost:10010/user/1?authorization=admin时