Spring cloud Gateway(二) 一个Http请求的流程解析

Spring Cloud Gateway 请求处理流程解析
本文详细解析了Spring Cloud Gateway处理HTTP请求的流程,包括路由匹配、Filter处理、请求发送和响应处理。通过示例代码和调试,揭示了从路由查找、请求发送到响应接收的内部工作机制,涉及关键类如RoutePredicate、FilteringWebHandler和NettyRoutingFilter等。

Spring cloud Gateway(二) 一个Http请求的流程解析


简介

    通过一个简单示例,debug出Spring Cloud Gateway的一个HTTP请求的处理流程

思路整理

    在上篇文章中大致了解了SpringCloudGateway的大致作用和关键模块(路由匹配和Filter),在这篇文章中将梳理出一个HTTP请求的处理链路

    目前先不关心其具体细节,主要梳理出其路由匹配的核心处理类,请求和响应的处理流向核心类

    需要的一些前置知识:netty相关使用经验,因为分析大量用到了netty相关概念的类比和猜测

示例代码

    配置启动一个简单的程序,请求转发到后台服务器,在请求和响应上添加一些东西,程序代码大致如下:

@SpringBootApplication
public class Application {
   
   

	public static void main(String[] args) {
   
   
		SpringApplication.run(Application.class, args);
	}

	@Bean
	public RouteLocator myRoutes(RouteLocatorBuilder builder) {
   
   
		return builder.routes()
				.route(p -> p.path("/")
						.filters(f -> f.addRequestParameter("test", "test")
								.addResponseHeader("return", "return"))
						.uri("http://localhost:8082/"))
				.build();
	}
}

相关处理类查找

路由匹配

    首先在没有打任何断点的情况下运行一次程序:把程序跑起来,访问 http://localhost:8080/,成功得到结果。通过查看日志,发现有下面关于路由匹配的语句:

o.s.c.g.h.p.RoutePredicateFactory        : Pattern "[/image/webp]" does not match against value "/"
o.s.c.g.h.p.RoutePredicateFactory        : Pattern "/" matches against value "/"
o.s.c.g.h.RoutePredicateHandlerMapping   : Route matched: 606b3b86-7ef4-4538-bbcb-b512c411c325

    一眼便看到 Route matched,还有类名带有 RoutePredicate,这大概率是路由匹配的核心处理类了,于是我们直接搜索打开这个类,看到下面的关键内容:

public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
   
   
    // 这 lookupRoute 方法名一看就是妥妥的路由查找
	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;
				});
	}
}

    路由匹配找到这个就差不多了,具体的比如路由如何加载、查找后如何调整到处理链,到后面在此处打断点,通过调用栈应该可以看到

Filter处理

Request处理发送

    一样通过查看debug日志,可以看到下面明显的日志:

o.s.c.g.handler.FilteringWebHandler      : Sorted gatewayFilterFactories: 
o.s.c.g.filter.RouteToRequestUrlFilter   : RouteToRequestUrlFilter start

    首先查看 RouteToRequestUrlFilter,发现其中没有明显的处理链(根据写网关的Filter的经验或者Netty的pipeline,应该入口是一个列表的循环处理或者定义的地方)。

    于是我们打开另外一个类:FilteringWebHandler,很幸运,看到filters,还有其get方法,很像,大致如下:

public class FilteringWebHandler implements WebHandler {
   
   
    ......

	private static class DefaultGatewayFilterChain implements GatewayFilterChain {
   
   

		@Override
		public Mono
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值