spring cloud gateway 源码一总体执行流程

gateway 源码

gateway 执行流程

  • RouteLocator 初始化配置
  • DispatcherHandler 请求分发
  • RoutePredicateHandlerMapping 路由匹配断言
  • FilteringWebHandler 过滤器链支持前置后置

RouteLocator

RouteLocator 与 RouteDefinitionLocator:相当于 Bean 和 BeanDefinition 的关系

RouteDefinitionRouteLocator:依赖 RouteDefinition 通过 convertToRoute 将 definition 转换为 route
    GatewayProperties properties
	List<GatewayFilterFactory> gatewayFilters 过滤器工厂类
	List<RoutePredicateFactory> predicates      谓词/断言工厂类
	RouteDefinitionLocator routeDefinitionLocator   路由定义定位器
	ConversionService conversionService 转换服务 
CachingRouteLocator 装饰 CompositeRouteLocator
CompositeRouteLocator 组合 List<RouteLocator> 即包括 RouteDefinitionRouteLocator
  • RouteDefinitionLocator的职责是将各种配置源的配置数据转化成RouteDefinition,而RouteLocator的职责是把RouteDefinition转化成Route
RouteDefinitionRouteLocator 类
// RouteDefinition转化成Route
@Override
public Flux<Route> getRoutes() {
    //获取到所有的RouteDefinition
    return this.routeDefinitionLocator.getRouteDefinitions()
            //遍历转换成对应的Route信息
            .map(this::convertToRoute)
            //TODO: error handling 异常处理
            .map(route -> {
                if (logger.isDebugEnabled()) {
                    logger.debug("RouteDefinition matched: " + route.getId());
                }
                return route;
            });
}

convertToRoute功能,谓词组装和过滤器组装

//获取routeDefinition中的Predicate 
//(通过combinePredicates方法)
// 不同的谓词器 and 短路操作 predicate = predicate.and(found); 
// lookup 方法将 PredicateDefinition 转换为 Predicate 即通过 RoutePredicateFactory

//获取routeDefinition中的GatewayFilter
//(通过gatewayFilters方法向下 loadGatewayFilters 方法通过 GatewayFilterFactory)
//build 路由信息
private Route convertToRoute(RouteDefinition routeDefinition) {
    //获取routeDefinition中的Predicate信息
	AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);
	//获取routeDefinition中的GatewayFilter信息
	List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);
    //构建路由信息
	return Route.async(routeDefinition).asyncPredicate(predicate)
			.replaceFilters(gatewayFilters).build();
}

combinePredicates 的 lookup方法,谓词器

private Predicate<ServerWebExchange> lookup(RouteDefinition route, PredicateDefinition predicate) {
    // 谓词工厂
    RoutePredicateFactory<Object> factory = this.predicates.get(predicate.getName());
	if (factory == null) {
		throw new IllegalArgumentException(
				"Unable to find RoutePredicateFactory with name "
						+ predicate.getName());
	}
	// 谓词参数
	Map<String, String> args = predicate.getArgs();
	if (logger.isDebugEnabled()) {
		logger.debug("RouteDefinition " + route.getId() + " applying " + args + " to "
				+ predicate.getName());
	}
    // 组装参数
	Map<String, Object> properties = factory.shortcutType().normalize(args, factory,
			this.parser, this.beanFactory);
	// 工厂配置类
	Object config = factory.newConfig();
	ConfigurationUtils.bind(config, properties, factory.shortcutFieldPrefix(),
			predicate.getName(), validator, conversionService);
	if (this.publisher != null) {
		this.publisher.publishEvent(
				new PredicateArgsEvent(this, route.getId(), properties));
	}
	// 工厂创建谓词器
	return factory.applyAsync(config);
}

getFilters 过滤器

// 根据 filterDefinitions 加载过滤器
List<GatewayFilter> loadGatewayFilters(String id,
			List<FilterDefinition> filterDefinitions) {
	ArrayList<GatewayFilter> ordered = new ArrayList<>(filterDefinitions.size());
	for (int i = 0; i < filterDefinitions.size(); i++) {
	    // FilterDefinition 配置的过滤器定义
		FilterDefinition definition = filterDefinitions.get(i);
		// 1. 通过定义获取过滤器工厂类
		GatewayFilterFactory factory = this.gatewayFilterFactories
				.get(definition.getName());
		if (factory == null) {
			throw new IllegalArgumentException(
					"Unable to find GatewayFilterFactory with name "
							+ definition.getName());
		}
		// 2. 过滤器参数
		Map<String, String> args = definition.getArgs();
		if (logger.isDebugEnabled()) {
			logger.debug("RouteDefinition " + id + " applying filter " + args + " to "
					+ definition.getName());
		}
        // 3. 组装参数
		Map<String, Object> properties = factory.shortcutType().normalize(args,
				factory, this.parser, this.beanFactory);
        // 4. 工厂配置类
		Object configuration = factory.newConfig();

		ConfigurationUtils.bind(configuration, properties,
				factory.shortcutFieldPrefix(), definition.getName(), validator);

		// some filters require routeId 部分过滤器必须有路由 id 通过上级传入下级调用
		// TODO: is there a better place to apply this?
		if (configuration instanceof HasRouteId) {
			HasRouteId hasRouteId = (HasRouteId) configuration;
			hasRouteId.setRouteId(id);
		}
        // 5. 根据配置类创建过滤器
		GatewayFilter gatewayFilter = factory.apply(configuration);
		if (this.publisher != null) {
		    // 发布事件
			this.publisher.publishEvent(new FilterArgsEvent(this, id, properties));
		}
		// 过滤器必须实现排序接口
		if (gatewayFilter instanceof Ordered) {
			ordered.add(gatewayFilter);
		}
		else {
		    // 不实现排序接口则需要静态代理增加功能
			ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1));
		}
	}
	return ordered;
}

private List<GatewayFilter> getFilters(RouteDefinition routeDefinition) {
	List<GatewayFilter> filters = new ArrayList<>();
    //是否配置默认的过滤器集合
	// TODO: support option to apply defaults after route specific filters?
	if (!this.gatewayProperties.getDefaultFilters().isEmpty()) {
	    //加载全局的默认过滤器集合
		filters.addAll(loadGatewayFilters(DEFAULT_FILTERS,
				this.gatewayProperties.getDefaultFilters()));
	}
    // 配置的局部过滤器集合
	if (!routeDefinition.getFilters().isEmpty()) {
		filters.addAll(loadGatewayFilters(routeDefinition.getId(),
				routeDefinition.getFilters()));
	}
    // 过滤器通过 order 排序
	AnnotationAwareOrderComparator.sort(filters);
	return filters;
}

自定义 RouteLocator

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { 
    return builder.routes()
            .route(r -> r.host("**.abc.org").and().path("/image/png")
                .filters(f ->
                        f.addResponseHeader("X-TestHeader", "foobar"))
                .uri("http://httpbin.org:80")
            )
            .build();
}

CachingRouteLocator 基于缓存

装饰 CompositeRouteLocator
实现 ApplicationListener 接口监听刷新事件对缓存进行刷新 RefreshRoutesEvent 事件

RefreshRoutesEvent 事件的触发机制

gateway 暴露的路由修改接口生成 RefreshRoutesEvent 事件
    endpoint 接口 gateway/refresh 刷新
监听心跳事件触发 RefreshRoutesEvent 事件
    RouteRefreshListener 类
    onApplicationEvent 方法监听 HeartbeatEvent 事件执行 reset 方法
    如果注册中心用 nacos 则通过 NacosWatch 类触发 HeartbeatEvent 事件
        NacosDiscoveryProperties
        private long watchDelay = 30000L
        默认间隔 30s 触发心跳

RoutePredicateHandlerMapping

FilteringWebHandler.DefaultGatewayFilterChain 过滤器链,包含局部过滤器和全局过滤器,根据 order 排序

RoutePredicateHandlerMapping 继承 webflux 的 AbstractHandlerMapping,

  • 组合 FilteringWebHandler
  • RouteDefinitionLocator 默认 CompositeRouteDefinitionLocator
CompositeRouteDefinitionLocator 组合 List<RouteDefinitionLocator> 默认有两个
    InMemoryRouteDefinitionRepository 可实现存储器替换
    PropertiesRouteDefinitionLocator    配置文件读取

PropertiesRouteDefinitionLocator 依赖于配置文件 GatewayProperties
    若是 nacos 配置中心则 GatewayProperties 支持自动配置,gateway 半分钟 refresh 一次获取新配置
  • RouteLocator 默认 CachingRouteLocator(cachedCompositeRouteLocator 不存在)
@Bean
@Primary
@ConditionalOnMissingBean(name = "cachedCompositeRouteLocator")
// TODO: property to disable composite?
public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {
	return new CachingRouteLocator(
			new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
}
RouteDefinitionRouteLocator:依赖 RouteDefinition 通过 convertToRoute 将 definition 转换为 route
    GatewayProperties properties
	List<GatewayFilterFactory> gatewayFilters 过滤器工厂类
	List<RoutePredicateFactory> predicates      谓词/断言工厂类
	RouteDefinitionLocator routeDefinitionLocator   
	    路由定义定位器,默认 CompositeRouteDefinitionLocator
	ConversionService conversionService 转换服务 
CachingRouteLocator 装饰 CompositeRouteLocator
CompositeRouteLocator 组合 List<RouteLocator> 即包括 RouteDefinitionRouteLocator

RoutePredicateHandlerMapping 的 getHandlerInternal 方法执行 lookupRoute 对上下文
ServerWebExchange 进行路由匹配

FilteringWebHandler

FilteringWebHandler 的 handle 组装责任链

return new DefaultGatewayFilterChain(combined).filter(exchange)
每次请求一个责任链,相当于集合每次遍历一个迭代器

责任链 DefaultGatewayFilterChain

private static class DefaultGatewayFilterChain implements GatewayFilterChain {
    // 当前链的索引
	private final int index;
    // 享元对象,每次传递引用
	private final List<GatewayFilter> filters;
	
	private DefaultGatewayFilterChain(DefaultGatewayFilterChain parent, int index) {
		this.filters = parent.getFilters();
		this.index = index;
	}
    
    /**
        核心
     */
	@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);
				// 全部执行的责任链,每次传递上下文信息和当前链
				// 过滤器需要执行 chain 的 filter 方法
				return filter.filter(exchange, chain);
			}
			else {
				return Mono.empty(); // complete
			}
		});
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud Gateway 是一个基于 Spring Framework 5、Spring Boot 2 和 Project Reactor 的 API 网关服务。它提供了一种简单而强大的方法来路由和过滤请求,并将它们转发到底层的微服务。对于理解 Spring Cloud Gateway 的工作原理和深入研究其源代码是非常有用的。 首先,通过源码可以发现 Spring Cloud Gateway 主要由三个核心模块组成:路由模块、过滤器模块和事件模块。路由模块负责根据定义的路由规则将请求转发到特定的目标地址。过滤器模块负责在请求的不同阶段执行一系列的过滤器来处理请求。事件模块则用于处理与路由和过滤器相关的异步事件。 源码中的路由模块使用了 Reactive Streams API 中的 Flux 和 Mono 类来处理异步操作。它利用 RouterFunction 和 HandlerFunction 来定义路由和处理请求的方法,并通过 RoutePredicateFactory 来解析和匹配路由规则。在路由模块中,使用了 Netty 库来实现底层的网络通信和请求转发。 通过源码分析过滤器模块,可以发现 Spring Cloud Gateway 的过滤器分为全局过滤器和自定义过滤器两种类型。全局过滤器在请求的全局范围内应用,并且可以用于添加一些全局的处理逻辑。自定义过滤器则允许开发者根据需要添加自定义的过滤逻辑。过滤器的执行顺序可以通过 Order 注解来控制,以满足不同过滤器的执行顺序需求。 事件模块在源码中使用了 Reactor 提供的 EventProcessor 来处理与路由和过滤器相关的事件。它使用了 Reactor 的 FluxSink 和 MonoSink 来创建异步事件源,并通过事件处理器将事件发送给注册的监听器。通过查看事件模块的源码,可以更加深入地了解 Spring Cloud Gateway 是如何处理与路由和过滤器相关的事件的。 总结而言,通过源码分析 Spring Cloud Gateway,我们可以更好地了解其内部的工作原理和实现细节。这对于开发者来说是非常有用的,因为它可以帮助我们更好地使用和扩展 Spring Cloud Gateway 来满足不同的场景需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值