1、调试网关请求的必要性:
微服务开发时,有时会遇到配置的断言工厂不生效访问404,过滤器工厂不生效等问题,这时就需要跟踪请求进行源码调试,但Gateway源码较为复杂,不熟悉开发人员可能连源码入口都找不到,调试更是无从下手。
2、源码入口
熟悉springboot开发人员,或者经常写一些starter组件的开发人员都知道很多springboot组件都会通过MEATA-INF/spring.factories文件自动装配Bean,SpringCloud Gateway也不例外,相关的配置也都在该配置加载类中。 SpringCloud Gateway和SpringMVC功能类似,都是接受一个请求,处理后转发给后续的handler处理,SpringMVC有一个handlerMapping用于匹配请求url和Controller方法,SpringCloud Gateway也是类似,也有一个HandlerMapping类,该类就在GatewayAutoConfiguration装配类中加载的,当然该装配类除了加载RoutePredicateHandlerMapping类外,还会加载一些内置断言工厂类如Path断言工厂、Header断言工厂等,加载一些内置的过滤器工厂等其他类;
spring.factories截图
RoutePredicateHandlerMapping
3、断言过程
RoutePredicateHandlerMapping类中的需要关注的代码就是getHandler相关的代码,如下图。代码很多,核心代码就是 r.getPredicate().apply(exchange)这一句,据此断言那个路由符合条件;如果没有匹配到断言工厂则返回404,如果匹配到了断言工厂,则开始执行全局过滤器,然后执行匹配到的断言工厂下配置的局部过滤器filters。
4、Debug跟踪
在网关的配置文件中配置了如下2个简单的断言工厂,通过网关(9001)访问后端admin(9003)暴露的接口:/test/user
后端服务:http://localhost:9003/test/user
请求网关:http://localhost:9001/admin/test/user
# 如下router应该配置到Nacos中,
gateway:
discovery:
locator:
enabled: false
lowerCaseServiceId: true
routes:
# auth应用服务
- id: auth
uri: lb://auth
predicates:
- Path=/auth/**
filters:
- StripPrefix=1
# admin服务
- id: admin
uri: lb://admin
predicates:
- Path=/admin/**
filters:
- StripPrefix=1
getHandlerInternal方法中其实是没有啥逻辑的,就是在put、remove一些属性,关注的断言逻辑在lookupRoute方法中。在return r.getPredicate().apply(exchange)这一行代码打断点,浏览器发起请求;
断点第一次拦截时debug信息如下,可以看到r.predicate的path信息和exchange中的path信息并不匹配(请求的是admin服务,加载route信息是auth服务的),此时return 返回false;
F9进入下一个断点,此时可以看到请求的路径和加载路由断言信息是匹配的,后续将执行全局过滤器、当前匹配到的断言下的局部过滤器(如果配置了的话),我这里在项目中配置了一个全局的日子链路id过滤器,此时按下F9将会调到该全局过滤器断点中(按优先级高低依次进入)。
全局过滤器