gateway是springcloud官方推出网关,用于取代netflix的zuul。
gateway基于WebFlux,底层使用Netty,性能强劲、功能多样,但
- 不支持springboot 1.x
- 不能在servlet容器下工作,不能打成war包
搭建getway网关
创建时勾选 SpringCloud Routing -> Getway,也可以手动添加依赖
<!--要注册到注册中心上-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
#启用智能路由,从注册中心拉取服务按照服务名路由
discovery:
locator:
enabled: true
#同时支持自定义路由配置
#routes:
说明:getway内置了ribbon实现负载均衡,内置了hystrix实现容错。
路由断言Predicate
Predicate 断言,也叫做谓词,来源于Java8,接受输入参数,返回一个布尔值结果。gateway利用 Predicate 的特性实现了多种路由转发的判断条件,满足指定的Predicate后才会进行路由转发。
gateway内置了多种断言,名称为 XxxRoutePredicateFactory,可以同时搭配使用多种断言,设置时取RoutePredicateFactory前面部分单词即可。
gateway 过滤器
过滤器的作用时机
- pre: 请求被路由到服务之前执行,一般用于鉴权、限流等
- post:服务返回响应到网关后、网关返回给客户端响应之前执行,可用于修改响应结果
gateway的过滤器可分为
- 局部过滤器:作用在指定路由上,gateway内置了多种局部过滤器,可以使用内置的,也可以继承下来重写方法。不管是内置的、还是自定义的,局部过滤器的类名都要以GatewayFilterFactory结尾。
- 全局过滤器:作用在全部路由上,可以使用内置的,也可以自定义。
demo 全局过滤器的使用
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component //放到容器中
@Slf4j //实现 GlobalFilter, Ordered 2个接口
public class LoginGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//要进行的过滤操作
String token = exchange.getRequest().getHeaders().getFirst("token");
log.info("token:{}", token);
if(StringUtils.isBlank(token)){
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
//return终止后续操作
return exchange.getResponse().setComplete();
}
//继续后续执行
return chain.filter(exchange);
}
@Override
public int getOrder() {
//order指定过滤器优先级,数字越小,优先级越高
return 0;
}
}
测试时可以在postman的header中传一个token字段。
网关尽量轻量,加太多的业务逻辑会影响性能。对个别服务的业务处理逻辑可以写在服务自身中。
gateway实现网关限流
gateway的内置过滤器 RequestRateLimiterGatewayFilterFactory 提供了限流能力,基于令牌桶算法实现,内置了RedisRateLimiter,使用Redis存储限流配置、统计数据。
也可以自己实现RateLimiter 接口,或继承AbstractRateLimiter,使用自定义的RateLimiter。