中国移动 面试 新闻api XML解析 工厂模式 pagination swagger Echojs Animsition vue前端开发 查看rabbitmq版本 oracle删除表字段 java解析json数组 maven配置eclipse python网络编程 python日期转时间戳 python编译环境 python安装 java教程 java重载和重写的区别 java中的数据结构 java获取当前年月 java定义变量 java当前日期 金山wps2003 bat脚本 手机照片恢复免费软件 vnc客户端 kmservice 只狼鬼佛 spss22安装教程 medcalc 大势至usb监控 hyqihei 苹果手机验机软件 小米9截屏 苹果手机不弹出信任 3dmax2014下载 kmplayer绿色版 js递归函数
当前位置: 首页 > 学习教程  > 编程语言

SpringCloudGateway小记

2020/8/31 14:37:01 文章标签:

GateWayProperties

public class GatewayProperties {
	/**
	 * List of Routes.
	 */
	private List<RouteDefinition> routes = new ArrayList<>();

	/**
	 * List of filter definitions that are applied to every route.
	 */
	private List<FilterDefinition> defaultFilters = new ArrayList<>();

	private List<MediaType> streamingMediaTypes = Arrays
			.asList(MediaType.TEXT_EVENT_STREAM, MediaType.APPLICATION_STREAM_JSON);

对应配置文件中:

spring:
  cloud:
    gateway:
      default-filters:
      - PrefixPath=/httpbin
      - AddResponseHeader=X-Response-Default-Foo, Default-Bar
      routes:
        - id: websocket_test
        uri: ws://localhost:9000
        order: 9000
        predicates:
        - Path=/echo
      # =====================================
      - id: default_path_to_httpbin
        uri: ${test.uri}
        order: 10000
        predicates:
        - Path=/**

List<FilterDefinition> defaultFilters

org.springframework.cloud.gateway.filter.FilterDefinition

public class FilterDefinition {
	private String name;
	private Map<String, String> args = new LinkedHashMap<>();
	public FilterDefinition(String text) {
		int eqIdx = text.indexOf('=');
		if (eqIdx <= 0) {
			setName(text);
			return;
		}
		setName(text.substring(0, eqIdx));

		String[] args = tokenizeToStringArray(text.substring(eqIdx + 1), ",");

		for (int i = 0; i < args.length; i++) {
			this.args.put(NameUtils.generateName(i), args[i]);
		}
	}
	
-------------
public final class NameUtils {
	/**
	 * Generated name prefix.
	 */
	public static final String GENERATED_NAME_PREFIX = "_genkey_";

	public static String generateName(int i) {
		return GENERATED_NAME_PREFIX + i;
	}

配置DEMO

spring: 
  cloud:
    gateway:
      default-filters:
      - PrefixPath=/httpbin
      - AddResponseHeader=X-Response-Default-Foo, Default-Bar

构造函数 参数只有一个字符串
name=value1,value2,value3,…
故每个FilterDefinition 的name与args 的Value 为外部配置,args 的Key 为自动生成 规则为 _genkey_+序号

List routes

org.springframework.cloud.gateway.route.RouteDefinition

public class RouteDefinition {
	private String id;
	private List<PredicateDefinition> predicates = new ArrayList<>();
	private List<FilterDefinition> filters = new ArrayList<>();
	private URI uri;
	private Map<String, Object> metadata = new HashMap<>();
	private int order = 0;
	public RouteDefinition() {
	}
	public RouteDefinition(String text) {
		int eqIdx = text.indexOf('=');
		if (eqIdx <= 0) {
			throw new ValidationException("Unable to parse RouteDefinition text '" + text
					+ "'" + ", must be of the form name=value");
		}
		setId(text.substring(0, eqIdx));
		String[] args = tokenizeToStringArray(text.substring(eqIdx + 1), ",");
		setUri(URI.create(args[0]));
		for (int i = 1; i < args.length; i++) {
			this.predicates.add(new PredicateDefinition(args[i]));
		}
	}

配置DEMO

spring:
  cloud:
    gateway:
      routes:
      - id: websocket_test
        uri: ws://localhost:9000
        order: 9000
        predicates:
        - Path=/echo
      # =====================================
      - id: default_path_to_httpbin
        uri: ${test.uri}
        order: 10000
        predicates:
        - Path=/**

List predicates

配置匹配表达式

public class PredicateDefinition {
	private String name;
	private Map<String, String> args = new LinkedHashMap<>();
	public PredicateDefinition() {
	}
	public PredicateDefinition(String text) {
		int eqIdx = text.indexOf('=');
		if (eqIdx <= 0) {
			throw new ValidationException("Unable to parse PredicateDefinition text '"
					+ text + "'" + ", must be of the form name=value");
		}
		setName(text.substring(0, eqIdx));
		String[] args = tokenizeToStringArray(text.substring(eqIdx + 1), ",");
		for (int i = 0; i < args.length; i++) {
			this.args.put(NameUtils.generateName(i), args[i]);
		}
	}

构造函数 参数只有一个字符串
name=value1,value2,value3,…
故每个PredicateDefinition 的name与args 的Value 为外部配置,args 的Key 为自动生成 规则为 _genkey_+序号

Route

org.springframework.cloud.gateway.route.Route
路由的基础单位
业务代码:

org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping#lookupRoute
public class Route implements Ordered {

	private final String id;

	private final URI uri;

	private final int order;
	/**
	 * 本路由的匹配规则
	 */
	private final AsyncPredicate<ServerWebExchange> predicate;
	/**
	 * 需要执行的过滤器
	 */
	private final List<GatewayFilter> gatewayFilters;

	private final Map<String, Object> metadata;

路由工厂

org.springframework.cloud.gateway.route.RouteLocator

/**
 * @author Spencer Gibb
 */
// TODO: rename to Routes?
public interface RouteLocator {

	Flux<Route> getRoutes();

}

默认的 SpringCloudGateWay 的 路由工厂使用

org.springframework.cloud.gateway.route.CachingRouteLocator

在这里插入图片描述

CachingRouteLocator 实现

org.springframework.cloud.gateway.config.GatewayAutoConfiguration#cachedCompositeRouteLocator

在这里插入图片描述


	public CachingRouteLocator(RouteLocator delegate) {
		this.delegate = delegate;
		routes = CacheFlux.lookup(cache, CACHE_KEY, Route.class)
				.onCacheMissResume(this::fetch);
	}

才用组合委托设计实现

基础 RouteLocator 定义

Bean 定义模式

 @Bean
    open fun additionalRouteLocator(builder: RouteLocatorBuilder) = builder.routes {
        route(id = "test-kotlin") {
            host("kotlin.abc.org") and path("/image/png")
            filters {
                prefixPath("/httpbin")
                addResponseHeader("X-TestHeader", "foobar")
            }
            uri(uri)
        }
    }
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")
            .filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis").addStatusCode("INTERNAL_SERVER_ERROR"))
                .rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")
        .build();
}

使用YAML 配置文件

spring:
  cloud:
    gateway:
      default-filters:
      - PrefixPath=/
      - AddResponseHeader=X-Response-Default-Foo, Default-Bar

      routes:
      - id: websocket_test
        uri: ws://localhost:9000
        order: 9000
        predicates:
        - Path=/echo

配置文件读取上GateWayProperties

配置文件实例化 RouteLocator

RouteDefinition 定义 RouteLocator

	public List<RouteDefinition> getRoutes() {
		return routes;
	}

org.springframework.cloud.gateway.config.PropertiesRouteDefinitionLocator

public class PropertiesRouteDefinitionLocator implements RouteDefinitionLocator {

	private final GatewayProperties properties;

	public PropertiesRouteDefinitionLocator(GatewayProperties properties) {
		this.properties = properties;
	}

	@Override
	public Flux<RouteDefinition> getRouteDefinitions() {
		return Flux.fromIterable(this.properties.getRoutes());
	}

}

在此加载 RouteLocator 的定义文件 (RouteDefinition)

org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getRoutes


	@Override
	public Flux<Route> getRoutes() {
		Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions()
				.map(this::convertToRoute);
	private Route convertToRoute(RouteDefinition routeDefinition) {
		AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);
		List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);

		return Route.async(routeDefinition).asyncPredicate(predicate)
				.replaceFilters(gatewayFilters).build();
	}

RouteDefinition 转换为 Router

Gateway 总路由

GateWay 映射

org.springframework.cloud.gateway.handler.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) + "]");
					}
				})));
	}

路由转发与过滤器

org.springframework.web.reactive.DispatcherHandler#handle
使用SpringWebFlux

	@Override
	public Mono<Void> handle(ServerWebExchange exchange) {
		if (this.handlerMappings == null) {
			return createNotFoundError();
		}
		return Flux.fromIterable(this.handlerMappings)
				.concatMap(mapping -> mapping.getHandler(exchange))
				.next()
				.switchIfEmpty(createNotFoundError())
				.flatMap(handler -> invokeHandler(exchange, handler))
				.flatMap(result -> handleResult(exchange, result));
	}


本文链接: http://www.dtmao.cc/news_show_150269.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?