- SpringCloud的第二代网关,未来会取代Zuul
- 基于Netty、Reactor、Webflux构建
优点:
- 性能强劲,是Zuul 1.X的1.6倍
- 功能强大,内置很多实用功能,如转发、监控、限流等
- 设计优雅,易扩展
缺点
- 依赖Netty与Webflux,不是Servlet编程模型,有一定适应成本
- 不能在Servlet容器下工作,不能构建war包
- 不支持springboot1.X
核心概念
Router(路由)
SpringCloud Gateway的基础元素,可以理解成一套转发的规则,包含ID、目标URL、Predicate集合以及Filter集合。
Predicate(谓词)
SpringCloud Gateway 使用Predicate实现路由的匹配条件。
Filter(过滤器)
修改请求以及响应。
结构
官网地址
GatewayClient: 泛指外部请求。
Gateway Handler Mapping: 根据请求匹配是否符合配置的路径,如果匹配就进入到Web Handler。
Gateway Web Handler: 读取配置上的过滤器,交给这些过滤器去处理。
Proxied Service: 被网关代理的微服务。
构建GateWay
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
namespace: 9b74b8d1-94ba-44ea-955b-2e174d42a14a
gateway:
discovery:
locator:
# 让gateway通过服务发现组件找到其他微服务
enabled: true
application:
name: getway
server:
port: 8040
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
启动,访问
访问:{Gateway_url}/{微服务名称}/{访问路径}
路由谓词工厂(Router Predicate Factories)
自定义路由谓词工厂
yml文件要UTF-8格式,不然启动的时候会报不发将String转LocalTime
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
namespace: 9b74b8d1-94ba-44ea-955b-2e174d42a14a
gateway:
discovery:
locator:
# 让gateway通过服务发现组件找到其他微服务
enabled: true
routes:
- id: after_route
uri: lb://user-center
predicates:
- TimeBetween=上午9:00,下午10:49
application:
name: getway
server:
port: 8040
@Data
public class TimeBeweenConfig {
private LocalTime start;
private LocalTime end;
}
类名要以RoutePredicateFactory结尾
@Component
public class TimeBetweenRoutePredicateFactory extends AbstractRoutePredicateFactory<TimeBeweenConfig> {
public TimeBetweenRoutePredicateFactory() {
super(TimeBeweenConfig.class);
}
@Override
public Predicate<ServerWebExchange> apply(TimeBeweenConfig config) {
LocalTime start = config.getStart();
LocalTime end = config.getEnd();
return exchange -> {
LocalTime now = LocalTime.now();
return now.isAfter(start) && now.isBefore(end);
};
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("start", "end");
}
public static void main(String[] args) {
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
System.out.println(formatter.format(LocalTime.now()));
}
}
过滤器工厂
自定义过滤工厂
过滤器生命周期
pre:Gateway转发请求之前
post:Gateway转发请求之后
自定义过滤工厂-方式1
继承:AbstractGatewayFilterFactory
参考:org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory
spring:
cloud:
gateway:
routes:
filters:
- name: RequestSize
args:
maxSize: 5000000
自定义过滤工厂-方式2
继承:AbstractNameValueGatewayFilterFactory
参考代码:org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory
spring:
cloud:
gateway:
routes:
filters:
- AddRequestHeader=S-Header, Bar
这种方式其实是继承了AbstractGatewayFilterFactory,是它的简化版
核心API
修改request
exchange.getRequest().mutate.xxx
修改exchange
exchange.mutate().xxx
传递给下一个过滤器处理
chain.filter(exchange)
拿到响应
exchange.getResponse()
自定义过滤工厂
类名需要以GatewayFilterFactory结尾
@Slf4j
@Component
public class PreLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return ((exchange, chain) -> {
log.info("请求进来了...,{},{}",config.getName(),config.getValue());
ServerHttpRequest modifiedRequest = exchange.getRequest()
.mutate()
.build();
ServerWebExchange modifiedExchage = exchange.mutate()
.request(modifiedRequest).build();
return chain.filter(modifiedExchage);
});
}
}
spring:
cloud:
gateway:
discovery:
locator:
# 让gateway通过服务发现组件找到其他微服务
enabled: true
routes:
filters:
- PreLog=a,b
全局过滤器
监控Spring Cloud Gateway
排错调优技巧
过滤器执行顺序
1.在执行顺序中有一个order的值,order值越小,越靠前执行。
2.局部过滤器的Order会按照配置从1开始递增
routes:
- id: after_route
uri: lb://user-center
predicates:
- TimeBetween=上午9:00,下午10:49
filters:
- PreLog=a,b # 1
- AddReq=b,c # 2
- AddRes=c,d # 3
3.如果配置了默认过滤器,也是默认从1开始递增。如果有两个相同的order,那么就会先执行默认过滤器的AddResponseHeader -> 自定义的AddResponseHeader -> PrefixPath -> PreLog -> AddRequestHeader
4.如果需要自己控制order,需要返回OrderedGatewayFilter
@Component
public class PreLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
GatewayFilter filter = ((exchange, chain) -> {
log.info("请求进来了...,{},{}",config.getName(),config.getValue());
ServerHttpRequest modifiedRequest = exchange.getRequest()
.mutate()
.build();
ServerWebExchange modifiedExchage = exchange.mutate()
.request(modifiedRequest).build();
return chain.filter(modifiedExchage);
});
// 自己设置的order为1000
return new OrderedGatewayFilter(filter, 1000);
}
}
Gateway限流
总结
1.注册到Nacos,能在Nacos上找到实例,反向代理
2.集成Ribbon,如果有多个实例,也是可以负载均衡
3.容错(默认Hystrix,也可以用Sentinel)