简介
SpringCloud Gateway为新一代微服务网关,可用于微服务中请求转发、负载均衡、权限控制/鉴权、熔断/限流/降级、日志、安全策略等功能;该项目基于springWebflux实现,使用netty作为web服务器;包含Filter(过滤器)、Route(路由)、Predicate(断言)三种术语。
实战笔记
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
#服务注册与发现
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
#熔断降级
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
常用配置
spring:
application:
name: gateway-demo
cloud:
gateway:
discovery:
locator:
#表明gateway开启服务注册和发现的功能,并且spring cloud gateway自动根据服务发现为每一个服务创建了一个router,这个router将以服务名开头的请求路径转发到对应的服务
enabled: true
#是将请求路径上的服务名配置为小写(因为服务注册的时候,向注册中心注册时将服务名转成大写的了
lower-case-service-id: true
# globalcors:
# cors-configurations:
# #跨域访问
# allowedOrigins: "http://baidu.com"
# allowedMethods:
# - GET
# allowHeaders:
# - Content-Type
#路由
routes:
- id: baidu
uri: https://baidu.com
predicates:
- Path=/baidu/**
filters:
- StripPrefix=1
- id: method_routh
#负载均衡
uri: lb://demo
#断言
predicates:
- Path=/feign/**
#过滤器
filters:
- StripPrefix=1
#自定义过滤器
- RequestTime
#熔断降级
- name: Hystrix
args:
name: fallbackcmd
#降级接口
fallbackUri: forward:/fallback
#重试
- name: Retry
args:
#重试次数
retries: 3
#HTTP 的状态返回码
status: 503
nacos:
discovery:
server-addr: localhost:8848
namespace: cg
自定义过滤器
全局过滤器
@Component
public class LogFilter implements GlobalFilter, Ordered {
private Logger logger = LoggerFactory.getLogger(LogFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
logger.info("request=" + exchange.getRequest().getURI().getRawPath() + " " + String.join(",", exchange.getRequest().getQueryParams().keySet()));
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
局部过滤器
public class RequestTimeFilter implements GatewayFilter, Ordered {
private Logger logger = LoggerFactory.getLogger(RequestTimeFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
Long startTime = System.currentTimeMillis();
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
logger.info("请求路径" + exchange.getRequest().getURI().getRawPath() + " 耗时" + (System.currentTimeMillis() - startTime) + "ms");
}));
}
@Override
public int getOrder() {
return 0;
}
}
@Component
public class RequestTimeGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
@Override
public GatewayFilter apply(Object config) {
return new RequestTimeFilter();
}
}
源码浅析
处理流程

网关处理流程
DispatcherHandler
//将请求映射到处理对象
@Nullable
private List<HandlerMapping> handlerMappings;
//用于使用任何处理程序接口
@Nullable
private List<HandlerAdapter> handlerAdapters;
//处理程序返回值
@Nullable
private List<HandlerResultHandler> resultHandlers;
//初始化处理器
protected void initStrategies(ApplicationContext context) {
Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerMapping.class, true, false);
ArrayList<HandlerMapping> mappings = new ArrayList<>(mappingBeans.values());
AnnotationAwareOrderComparator.sort(mappings);
this.handlerMappings = Collections.unmodifiableList(mappings);
Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerAdapter.class, true, false);
this.handlerAdapters = new ArrayList<>(adapterBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerResultHandler.class, true, false);
this.resultHandlers = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(this.resultHandlers);
}
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (this.handlerMappings == null) {
return createNotFoundError();
}
return Flux.fromIterable(this.handlerMappings)
//获取映射处理器FilteringWebHandler
.concatMap(mapping -> mapping.getHandler(exchange))
.next()
//空异常
.switchIfEmpty(createNotFoundError())
.flatMap(handler -> invokeHandler(exchange, handler))
.flatMap(result -> handleResult(exchange, result));
}
private <R> Mono<R> createNotFoundError() {
return Mono.defer(() -> {
Exception ex = new ResponseStatusException(HttpStatus.NOT_FOUND, "No matching handler");
return Mono.error(ex);
});
}
//过滤器处理
private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
if (this.handlerAdapters != null) {
for (HandlerAdapter handlerAdapter : this.handlerAdapters) {
if (handlerAdapter.supports(handler)) {
return handlerAdapter.handle(exchange, handler);
}
}
}
return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
}
//处理返回值
private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
return getResultHandler(result).handleResult(exchange, result)
.onErrorResume(ex -> result.applyExceptionHandler(ex).flatMap(exceptionResult ->
getResultHandler(exceptionResult).handleResult(exchange, exceptionResult)));
}
private HandlerResultHandler getResultHandler(HandlerResult handlerResult) {
if (this.resultHandlers != null) {
for (HandlerResultHandler resultHandler : this.resultHandlers) {
if (resultHandler.supports(handlerResult)) {
return resultHandler;
}
}
}
throw new IllegalStateException("No HandlerResultHandler for " + handlerResult.getReturnValue());
}
RoutePredicateHandlerMapping
@Override
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
// don't handle requests on management port if set and different than server port
if (this.managementPortType == DIFFERENT && this.managementPort != null
&& exchange.getRequest().getURI().getPort() == this.managementPort) {
return Mono.empty();
}
exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getSimpleName());
//获取路由处理器
return lookupRoute(exchange)
// .log("route-predicate-handler-mapping", Level.FINER) //name this
.flatMap((Function<Route, Mono<?>>) r -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
if (logger.isDebugEnabled()) {
logger.debug(
"Mapping [" + getExchangeDesc(exchange) + "] to " + r);
}
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
return Mono.just(webHandler);
}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
if (logger.isTraceEnabled()) {
logger.trace("No RouteDefinition found for ["
+ getExchangeDesc(exchange) + "]");
}
})));
}
protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
return this.routeLocator.getRoutes()
// individually filter routes so that filterWhen error delaying is not a
// problem
.concatMap(route -> Mono.just(route).filterWhen(r -> {
// add the current route we are testing
exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
return r.getPredicate().apply(exchange);
})
// instead of immediately stopping main flux due to error, log and
// swallow it
.doOnError(e -> logger.error(
"Error applying predicate for route: " + route.getId(),
e))
.onErrorResume(e -> Mono.empty()))
// .defaultIfEmpty() put a static Route not found
// or .switchIfEmpty()
// .switchIfEmpty(Mono.<Route>empty().log("noroute"))
.next()
// TODO: error handling
.map(route -> {
if (logger.isDebugEnabled()) {
logger.debug("Route matched: " + route.getId());
}
validateRoute(route, exchange);
return route;
});
/*
* TODO: trace logging if (logger.isTraceEnabled()) {
* logger.trace("RouteDefinition did not match: " + routeDefinition.getId()); }
*/
}
FilteringWebHandler
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
List<GatewayFilter> gatewayFilters = route.getFilters();
//全局过滤器
List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
//局部过滤器
combined.addAll(gatewayFilters);
// TODO: needed or cached?
//Order排序
AnnotationAwareOrderComparator.sort(combined);
if (logger.isDebugEnabled()) {
logger.debug("Sorted gatewayFilterFactories: " + combined);
}
//过滤器链
return new DefaultGatewayFilterChain(combined).filter(exchange);
}
private static class DefaultGatewayFilterChain implements GatewayFilterChain {
private final int index;
private final List<GatewayFilter> filters;
DefaultGatewayFilterChain(List<GatewayFilter> filters) {
this.filters = filters;
this.index = 0;
}
private DefaultGatewayFilterChain(DefaultGatewayFilterChain parent, int index) {
this.filters = parent.getFilters();
this.index = index;
}
public List<GatewayFilter> getFilters() {
return filters;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange) {
return Mono.defer(() -> {
if (this.index < filters.size()) {
GatewayFilter filter = filters.get(this.index);
DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(this,
this.index + 1);
return filter.filter(exchange, chain);
}
else {
return Mono.empty(); // complete
}
});
}
}