精华内容
下载资源
问答
  • 动态路由

    2020-11-11 15:01:28
    动态路由协议一、路由的概述1、动态路由2、动态路由的特点3、动态路由协议概述4、度量值5、收敛6、静态路由与动态路由的比较7、按照路由执行的算法分类①距离矢量路由协议②链路状态路由协议二、RIP路由协议工作原理...

    一、路由的概述

    在这里插入图片描述

    1、动态路由

    基于某种路由协议实现

    2、动态路由的特点

    减少了管理任务

    占用了网络带宽

    3、动态路由协议概述

    路由器之间用来交换信息的语言

    4、度量值

    跳数、带宽、负载、时延、可靠性、成本

    路由器会通过度量值来确定最优路由路径

    在这里插入图片描述

    5、收敛

    使所有路由表都达到一致状态的过程

    6、静态路由与动态路由的比较

    网络中静态路由和动态路由互相补充

    7、按照路由执行的算法分类

    ①距离矢量路由协议

    依据从源网络到目标网络所经过的路由器的个数选择路由

    RIP、IGRP(思科私有协议)

    RIP协议主要是根据跳数

    ②链路状态路由协议

    综合考虑从源网络到目标网络的各条路径的情况选择路由

    OSPF、IS-IS

    二、RIP路由协议工作原理

    1、RIP是距离-矢量路由选择协议

    2、RIP的基本概念

    定期跟新

    邻居

    广播跟新

    全路由表更新

    3、路由表的形成

    路由器学习到直连路由

    更新周期30s到时,路由器会向邻居发送路由表

    再过30s,第二个跟新周期到了再次发送路由表

    在这里插入图片描述

    4、RIP的度量值与更新时间

    ①RIP度量值为跳数

    最大跳数为15跳,16跳为不可达

    ②RIP更新时间

    每隔30s发送路由跟新消息,UDP520端口

    5、RIP路由跟新消息

    发送整个路由表信息

    三、水平分割

    1、路由环路

    在这里插入图片描述

    2、执行水平分割可以组织路由环路的发生

    从一个接口学习到路由信息,不在从这个接口发送出去

    同时也能减少路由更新消息占用的链路带宽资源

    在这里插入图片描述

    补充:

    水平分割和毒性逆转主要是针对动态路由协议RIP中,避免路由环路,提高收敛速度产生的

    水平分割:在路由信息传送过程中,路由器从某个接口接收到的更新信息不允许再从这个接口发回去。同时也能减少路由更新信息占用的链路带宽资源

    毒性逆转:路由器从某个接口上接收到某个网段的路由信息之后,并不是不往回发送信息了,而是发送,只不过是将这个网段标志为不可达,在发送从出去。收到此种的路由信息后,接收方路由器会立刻抛弃该路由,而不是等待其老化时间到。这样可以加速路由的收敛。

    四、RIP路由协议V1与V2

    RIPv1和RIPv2的区别

    在这里插入图片描述

    五、RIP命令

    【1】rip 1 ###启动RIP

    【R1-rip-1】version 2 ###启动版本2(缺省为版本1)

    【R1-rip-1】undo summary ###关闭路由自动聚合(即所有路由信息都会按照IP地址分类归类)

    【R1-rip-1】network 192.168.10.0 ###宣告主网络号,V2会携带掩码组播更新224.0.0.9,v1不携带掩码广播更新255.255.255.255

    【R1-rip-1】network 200.1.1.0

    兼容模式

    【R1】int g0/0/1

    【R1-GigabitETHERNET0/0/1】rip version 2 multicast ###把设置成rip1路由器的某一接口单独设置成rip版本2

    展开全文
  • SpringCloudGateway动态路由(Redis持久化)以及请求到寻找路由的流程 1、路由加载流程简述 /** * 1、处理映射器加载路由 {@link RoutePredicateHandlerMapping#lookupRoute(ServerWebExchange)} * 2、路由加载器...

    SpringCloudGateway动态路由(Redis持久化)以及请求到寻找路由的流程

    1、路由加载流程简述

    /**
         * 1、处理映射器加载路由 {@link RoutePredicateHandlerMapping#lookupRoute(ServerWebExchange)}
         * 2、路由加载器获取路由 {@link RouteLocator#getRoutes()} ;{@link RouteLocator}注入到Spring容器的是统一入口{@link CachingRouteLocator},
         *    {@link CompositeRouteLocator#getRoutes()} 在 {@link GatewayAutoConfiguration#cachedCompositeRouteLocator(List)} 注入到Spring容器中,
         * 3、路由定义信息加载器 方法cachedCompositeRouteLocator 中 List<RouteLocator> routeLocators 中,
         *    其中之一{@link RouteDefinitionRouteLocator}
         *    在{@link GatewayAutoConfiguration#routeDefinitionRouteLocator(GatewayProperties, List, List,RouteDefinitionLocator, ConfigurationService)} 注入到Spring容器中,
         *    其中 {@link RouteDefinitionLocator}(路由定义信息加载器)是统一入口 {@link CompositeRouteDefinitionLocator} 在{@link GatewayAutoConfiguration#routeDefinitionLocator(List)}注入到Spring容器中,
         *    其中 List<RouteDefinitionLocator> routeDefinitionLocators 包含
         *    读取配置文件的 {@link GatewayAutoConfiguration#propertiesRouteDefinitionLocator(GatewayProperties)}
         *    不存在持久化bean的时候 {@link GatewayAutoConfiguration#inMemoryRouteDefinitionRepository()}
         * 4、加载路由定义信息 {@link RouteDefinitionLocator#getRouteDefinitions()} {@link CompositeRouteDefinitionLocator#getRouteDefinitions()} 会统一加载,所有的 RouteDefinitionLocator bean
         *
         * 流程如下 {@link RoutePredicateHandlerMapping#lookupRoute(ServerWebExchange)}
         *  {@link RouteLocator#getRoutes()} --[{@link CompositeRouteLocator#getRoutes()} {@link CachingRouteLocator#getRoutes()} 主要
         *  {@link RouteDefinitionRouteLocator#getRoutes()},初始化过滤器、断言等都在此类 ]
         *  {@link RouteDefinitionRouteLocator} 中的{@link RouteDefinitionLocator#getRouteDefinitions()}获取路由信息,{@link RouteDefinitionRouteLocator#convertToRoute(RouteDefinition)}
         *  路由信息转换为路由
         *
         *  RoutePredicateHandlerMapping 对应的映射,访问一次都会加载一次
         * @return
         */
    

    2、动态路由,redis存储

    • Controller
    @RestController
    public class GatewayRouteController extends GatewayBaseController{
    
        @Autowired
        DynamicRouteService routeService;
        @Autowired
        GatewayAppRouteRedisRepository redisRepository;
    
    //    @PostMapping(value = "add", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    //    public Response save(@RequestBody GatewayRouteDefinition definition) {
    //        routeService.save(definition);
    //        return Response.success();
    //    }
    
        @PostMapping("route/save_or_update")
        public Mono<RestResult> update(@RequestBody GatewayAppRoute definition) {
            routeService.update(definition);
            redisRepository.update(definition);
            return Mono.just(TRestBuilder.success());
        }
    
    
        @DeleteMapping("route/{id}")
        public Mono<RestResult> delete(@PathVariable("id") String id) {
            routeService.delete(id);
            redisRepository.delete(id);
            return Mono.just(TRestBuilder.success());
        }
    
        @PostMapping("routes")
        public Mono<RestResult<List<GatewayAppRoute>>> list() {
            return Mono.just(TRestBuilder.success(redisRepository.routeViews()));
        }
    }
    
    • 动态路由
    /**
     * 动态路由信息
     */
    public class DynamicRouteService implements ApplicationEventPublisherAware {
        @Autowired
        RouteDefinitionRepository routeDefinitionRepository;// 实现redis存储
    
        private ApplicationEventPublisher publisher;
        @Override
        public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
         this.publisher=applicationEventPublisher;
        }
    
        // 发布事件,刷新路由,实现动态路由
        private void publish() {
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
        }
    
        public void save(GatewayAppRoute definition){
            RouteDefinition routeDefinition=definition.routeDefinition();
            routeDefinitionRepository.save(Mono.just(routeDefinition)).subscribe();
            publish();
        }
    
    
        public void update(GatewayAppRoute definition){
            RouteDefinition routeDefinition=definition.routeDefinition();
            routeDefinitionRepository.delete(Mono.just(definition.getServiceId()));
            routeDefinitionRepository.save(Mono.just(routeDefinition)).subscribe();
            publish();
        }
    
    
        public void delete(String serviceId){
            routeDefinitionRepository.delete(Mono.just(serviceId));
            publish();
        }
    }
    
    • Redis持久化
    /**
     * 路由存储 redis
     */
    public class RouteDefinitionRedisRepository implements RouteDefinitionRepository,RouteRepository {
        final static String GATEWAY_ROUTES = "GATEWAY:ROUTE";
        @Autowired
        RedisCache redisCache;//redis操作,Redistemplate
    
        /**
         * 从redis加在路由信息
         * @return
         */
        public Map<String,RouteDefinition> loadRoute() {
            Map<String, RouteDefinition> data = redisCache.getCacheMap(GATEWAY_ROUTES, RouteDefinition.class);
            return data;
        }
    
        /**
         * 1、处理映射器加载路由 {@link RoutePredicateHandlerMapping#lookupRoute(ServerWebExchange)}
         * 2、路由加载器获取路由 {@link RouteLocator#getRoutes()} ;{@link RouteLocator}注入到Spring容器的是统一入口{@link CachingRouteLocator},
         *    {@link CompositeRouteLocator#getRoutes()} 在 {@link GatewayAutoConfiguration#cachedCompositeRouteLocator(List)} 注入到Spring容器中,
         * 3、路由定义信息加载器 方法cachedCompositeRouteLocator 中 List<RouteLocator> routeLocators 中,
         *    其中之一{@link RouteDefinitionRouteLocator}
         *    在{@link GatewayAutoConfiguration#routeDefinitionRouteLocator(GatewayProperties, List, List,RouteDefinitionLocator, ConfigurationService)} 注入到Spring容器中,
         *    其中 {@link RouteDefinitionLocator}(路由定义信息加载器)是统一入口 {@link CompositeRouteDefinitionLocator} 在{@link GatewayAutoConfiguration#routeDefinitionLocator(List)}注入到Spring容器中,
         *    其中 List<RouteDefinitionLocator> routeDefinitionLocators 包含
         *    读取配置文件的 {@link GatewayAutoConfiguration#propertiesRouteDefinitionLocator(GatewayProperties)}
         *    不存在持久化bean的时候 {@link GatewayAutoConfiguration#inMemoryRouteDefinitionRepository()}
         * 4、加载路由定义信息 {@link RouteDefinitionLocator#getRouteDefinitions()} {@link CompositeRouteDefinitionLocator#getRouteDefinitions()} 会统一加载,所有的 RouteDefinitionLocator bean
         *
         * 流程如下 {@link RoutePredicateHandlerMapping#lookupRoute(ServerWebExchange)}
         *  {@link RouteLocator#getRoutes()} --[{@link CompositeRouteLocator#getRoutes()} {@link CachingRouteLocator#getRoutes()} 主要
         *  {@link RouteDefinitionRouteLocator#getRoutes()},初始化过滤器、断言等都在此类 ]
         *  {@link RouteDefinitionRouteLocator} 中的{@link RouteDefinitionLocator#getRouteDefinitions()}获取路由信息,{@link RouteDefinitionRouteLocator#convertToRoute(RouteDefinition)}
         *  路由信息转换为路由
         *
         *  RoutePredicateHandlerMapping 对应的映射,访问一次都会加载一次
         * @return
         */
        @Override
        public Flux<RouteDefinition> getRouteDefinitions() {
            List<RouteDefinition> routeDefinitions = new ArrayList<>();
            Map<String, RouteDefinition> data = loadRoute();
            if (!CollectionUtils.isEmpty(data)) {
                data.forEach((K, V) -> routeDefinitions.add(V));
            }
            return Flux.fromIterable(routeDefinitions);
        }
    
        @Override
        public Mono<Void> save(Mono<RouteDefinition> route) {
            return route.flatMap(routeDefinition -> {
                redisCache.putDataToCacheMap(GATEWAY_ROUTES, routeDefinition.getId(), routeDefinition);
                return Mono.empty();
            });
        }
    
        @Override
        public Mono<Void> delete(Mono<String> routeId) {
            return routeId.flatMap(id -> {
                if (redisCache.cacheMapHasKey(GATEWAY_ROUTES, id)) {
                    redisCache.deleteDataFromCacheMap(GATEWAY_ROUTES, id);
                    return Mono.empty();
                }
                return Mono.defer(() -> Mono.error(new NotFoundException("RouteDefinition not found: " + routeId)));
            });
        }
    
        @Override
        public List<RouteDefinition> loadRoutes() {
            Map<String,RouteDefinition> data=loadRoute();
            return CollectionUtils.isEmpty(data)?new ArrayList<>():new ArrayList<>(data.values());
        }
    }
    
    
    • GatewayAppRoute
    /**
     * APP 配置信息
     */
    @Data
    public class GatewayAppRoute {
        /**
         * 服务状态
         */
        private int serviceStatus;
        /**
         * 服务名称
         */
        @NotBlank(message = "serviceName不能为空")
        private String serviceName;
        /**
         * 服务版本号
         */
        @NotBlank(message = "serviceVersion不能为空")
        private String serviceVersion;
        /**
         * 路由ID(服务ID)
         */
        @NotBlank(message = "serviceId不能为空")
        private String serviceId;
        /**
         * 路由断言集合配置
         */
        @NotEmpty(message = "predicates不能为空")
        private List<GatewayDefinition> predicates = new ArrayList<>();
        /**
         * 路由过滤器集合配置
         */
        private List<GatewayDefinition> filters = new ArrayList<>();
        /**
         * 路由规则转发的目标uri
         *
         * 建议lb协议<lb://serviceId>
         */
        @NotBlank(message = "uri不能为空")
        private String uri;
        /**
         * 路由执行顺序
         */
        private int order = 0;
    
        @Data
        public static class GatewayDefinition {
            //断言(过滤器)对应的Name
            private String name;
            //配置的断言(过滤器)规则
            private Map<String,String> args=new LinkedHashMap<>();
        }
    
        public RouteDefinition routeDefinition(){
            RouteDefinition routeDefinition=new RouteDefinition();
            routeDefinition.setId(serviceId);
            routeDefinition.setOrder(order);
            URI routeUri = !StringUtils.startsWith(uri,"lb")?UriComponentsBuilder.fromHttpUrl(uri).build().toUri():URI.create(uri);
            routeDefinition.setUri(routeUri);
            if(!CollectionUtils.isEmpty(filters)){
                routeDefinition.setFilters(filters.stream().map(f->{
                    FilterDefinition filterDefinition=new FilterDefinition();
                    filterDefinition.setName(f.name);
                    filterDefinition.setArgs(f.args);
                    return filterDefinition;
                }).collect(Collectors.toList()));
            }
            if(!CollectionUtils.isEmpty(predicates)){
                routeDefinition.setPredicates(predicates.stream().map(f->{
                    PredicateDefinition predicateDefinition=new PredicateDefinition();
                    predicateDefinition.setName(f.name);
                    predicateDefinition.setArgs(f.args);
                    return predicateDefinition;
                }).collect(Collectors.toList()));
            }
            return routeDefinition;
        }
    }
    

    3. SpringCloudGateway 请求到寻找路由的流程

    DispatcherHandler
    package org.springframework.web.reactive;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    
    import reactor.core.publisher.Flux;
    import reactor.core.publisher.Mono;
    
    import org.springframework.beans.factory.BeanFactoryUtils;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.core.annotation.AnnotationAwareOrderComparator;
    import org.springframework.http.HttpStatus;
    import org.springframework.lang.Nullable;
    import org.springframework.web.server.ResponseStatusException;
    import org.springframework.web.server.ServerWebExchange;
    import org.springframework.web.server.WebHandler;
    import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
    
    /**
     * Central dispatcher for HTTP request handlers/controllers. Dispatches to
     * registered handlers for processing a request, providing convenient mapping
     * facilities.
     *
     * <p>{@code DispatcherHandler} discovers the delegate components it needs from
     * Spring configuration. It detects the following in the application context:
     * <ul>
     * <li>{@link HandlerMapping} -- map requests to handler objects
     * <li>{@link HandlerAdapter} -- for using any handler interface
     * <li>{@link HandlerResultHandler} -- process handler return values
     * </ul>
     *
     * <p>{@code DispatcherHandler} is also designed to be a Spring bean itself and
     * implements {@link ApplicationContextAware} for access to the context it runs
     * in. If {@code DispatcherHandler} is declared with the bean name "webHandler"
     * it is discovered by {@link WebHttpHandlerBuilder#applicationContext} which
     * creates a processing chain together with {@code WebFilter},
     * {@code WebExceptionHandler} and others.
     *
     * <p>A {@code DispatcherHandler} bean declaration is included in
     * {@link org.springframework.web.reactive.config.EnableWebFlux @EnableWebFlux}
     * configuration.
     *
     * @author Rossen Stoyanchev
     * @author Sebastien Deleuze
     * @author Juergen Hoeller
     * @since 5.0
     * @see WebHttpHandlerBuilder#applicationContext(ApplicationContext)
     */
    public class DispatcherHandler implements WebHandler, ApplicationContextAware {
    
    	@Nullable
    	private List<HandlerMapping> handlerMappings;
    
    	@Nullable
    	private List<HandlerAdapter> handlerAdapters;
    
    	@Nullable
    	private List<HandlerResultHandler> resultHandlers;
    
    
    	/**
    	 * Create a new {@code DispatcherHandler} which needs to be configured with
    	 * an {@link ApplicationContext} through {@link #setApplicationContext}.
    	 */
    	public DispatcherHandler() {
    	}
    
    	/**
    	 * Create a new {@code DispatcherHandler} for the given {@link ApplicationContext}.
    	 * @param applicationContext the application context to find the handler beans in
    	 */
    	public DispatcherHandler(ApplicationContext applicationContext) {
    		initStrategies(applicationContext);
    	}
    
    
    	/**
    	 * Return all {@link HandlerMapping} beans detected by type in the
    	 * {@link #setApplicationContext injected context} and also
    	 * {@link AnnotationAwareOrderComparator#sort(List) sorted}.
    	 * <p><strong>Note:</strong> This method may return {@code null} if invoked
    	 * prior to {@link #setApplicationContext(ApplicationContext)}.
    	 * @return immutable list with the configured mappings or {@code null}
    	 */
    	@Nullable
    	public final List<HandlerMapping> getHandlerMappings() {
    		return this.handlerMappings;
    	}
    
    	@Override
    	public void setApplicationContext(ApplicationContext applicationContext) {
    		initStrategies(applicationContext);
    	}
    
        // 初始化处理
    	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)
                     // 获取处理器,与已经注册好了的HandlerAdapter一一匹配
                     // org.springframework.web.reactive.handler.AbstractHandlerMapping#getHandler
                     //AbstractHandlerMapping 有多个子类,子类都会进入父类getHandler 
    				.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);
    		});
    	}
        // 看哪一种HandlerAdapter是支持该controller类型的
    	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)
    				.checkpoint("Handler " + result.getHandler() + " [DispatcherHandler]")
    				.onErrorResume(ex ->
    						result.applyExceptionHandler(ex).flatMap(exResult -> {
    							String text = "Exception handler " + exResult.getHandler() +
    									", error=\"" + ex.getMessage() + "\" [DispatcherHandler]";
    							return getResultHandler(exResult).handleResult(exchange, exResult).checkpoint(text);
    						}));
    	}
    
    	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());
    	}
    
    }
    
    

    其中 org.springframework.web.reactive.DispatcherHandler#handle(ServerWebExchange exchange)

    根据请求从handlerMappings获取对应的处理器映射,通过处理器映射,可以将web请求映射到正确的处理器(handler)上。

    @Override
    	public Mono<Object> getHandler(ServerWebExchange exchange) {
    		return getHandlerInternal(exchange).map(handler -> {
    			if (logger.isDebugEnabled()) {
    				logger.debug(exchange.getLogPrefix() + "Mapped to " + handler);
    			}
    			ServerHttpRequest request = exchange.getRequest();
    			if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
    				CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(exchange) : null);
    				CorsConfiguration handlerConfig = getCorsConfiguration(handler, exchange);
    				config = (config != null ? config.combine(handlerConfig) : handlerConfig);
    				if (!this.corsProcessor.process(config, exchange) || CorsUtils.isPreFlightRequest(request)) {
    					return REQUEST_HANDLED_HANDLER;
    				}
    			}
    			return handler;
    		});
    	}
    /**
    	 * Look up a handler for the given request, returning an empty {@code Mono}
    	 * if no specific one is found. This method is called by {@link #getHandler}.
    	 * <p>On CORS pre-flight requests this method should return a match not for
    	 * the pre-flight request but for the expected actual request based on the URL
    	 * path, the HTTP methods from the "Access-Control-Request-Method" header, and
    	 * the headers from the "Access-Control-Request-Headers" header.
    	 * @param exchange current exchange
    	 * @return {@code Mono} for the matching handler, if any
    	 */
    	protected abstract Mono<?> getHandlerInternal(ServerWebExchange exchange);
    

    在这里插入图片描述

    这里,看到了gateway的RoutePredicateHandlerMapping

    org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping

    RoutePredicateHandlerMapping

    org.springframework.cloud.gateway.config.GatewayAutoConfiguration 初始化

    package org.springframework.cloud.gateway.handler;
    
    import java.util.function.Function;
    
    import reactor.core.publisher.Mono;
    
    import org.springframework.cloud.gateway.config.GlobalCorsProperties;
    import org.springframework.cloud.gateway.route.Route;
    import org.springframework.cloud.gateway.route.RouteLocator;
    import org.springframework.core.env.Environment;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.reactive.handler.AbstractHandlerMapping;
    import org.springframework.web.server.ServerWebExchange;
    
    import static org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping.ManagementPortType.DIFFERENT;
    import static org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping.ManagementPortType.DISABLED;
    import static org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping.ManagementPortType.SAME;
    import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_HANDLER_MAPPER_ATTR;
    import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR;
    import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
    
    /**
     * @author Spencer Gibb
     */
    public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
    
       private final FilteringWebHandler webHandler;
       // 路由统一加载的实例(org.springframework.cloud.gateway.route.CompositeRouteLocator)
       // org.springframework.cloud.gateway.route.CachingRouteLocator
       private final RouteLocator routeLocator;
    
       private final Integer managementPort;
    
       private final ManagementPortType managementPortType;
    
       public RoutePredicateHandlerMapping(FilteringWebHandler webHandler,
             RouteLocator routeLocator, GlobalCorsProperties globalCorsProperties,
             Environment environment) {
          this.webHandler = webHandler;
          this.routeLocator = routeLocator;
    
          this.managementPort = getPortProperty(environment, "management.server.");
          this.managementPortType = getManagementPortType(environment);
          setOrder(1);
          setCorsConfigurations(globalCorsProperties.getCorsConfigurations());
       }
    
       private ManagementPortType getManagementPortType(Environment environment) {
          Integer serverPort = getPortProperty(environment, "server.");
          if (this.managementPort != null && this.managementPort < 0) {
             return DISABLED;
          }
          return ((this.managementPort == null
                || (serverPort == null && this.managementPort.equals(8080))
                || (this.managementPort != 0 && this.managementPort.equals(serverPort)))
                      ? SAME : DIFFERENT);
       }
    
       private static Integer getPortProperty(Environment environment, String prefix) {
          return environment.getProperty(prefix + "port", Integer.class);
       }
    
        // 网关路由时进入此方法
       @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) + "]");
                   }
                })));
       }
    
       @Override
       protected CorsConfiguration getCorsConfiguration(Object handler,
             ServerWebExchange exchange) {
          // TODO: support cors configuration via properties on a route see gh-229
          // see RequestMappingHandlerMapping.initCorsConfiguration()
          // also see
          // https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/test/java/org/springframework/web/cors/reactive/CorsWebFilterTests.java
          return super.getCorsConfiguration(handler, exchange);
       }
    
       // TODO: get desc from factory?
       private String getExchangeDesc(ServerWebExchange exchange) {
          StringBuilder out = new StringBuilder();
          out.append("Exchange: ");
          out.append(exchange.getRequest().getMethod());
          out.append(" ");
          out.append(exchange.getRequest().getURI());
          return out.toString();
       }
    
       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()); }
           */
       }
    
       /**
        * Validate the given handler against the current request.
        * <p>
        * The default implementation is empty. Can be overridden in subclasses, for example
        * to enforce specific preconditions expressed in URL mappings.
        * @param route the Route object to validate
        * @param exchange current exchange
        * @throws Exception if validation failed
        */
       @SuppressWarnings("UnusedParameters")
       protected void validateRoute(Route route, ServerWebExchange exchange) {
       }
    
       protected String getSimpleName() {
          return "RoutePredicateHandlerMapping";
       }
    
       public enum ManagementPortType {
    
          /**
           * The management port has been disabled.
           */
          DISABLED,
    
          /**
           * The management port is the same as the server port.
           */
          SAME,
    
          /**
           * The management port and server port are different.
           */
          DIFFERENT;
    
       }
    
    }
    
    RouteLocator路由加载
    package org.springframework.cloud.gateway.route;
    
    import reactor.core.publisher.Flux;
    /** 
     * org.springframework.cloud.gateway.route.CachingRouteLocator 缓存,有事件监听
     * org.springframework.cloud.gateway.route.CompositeRouteLocator 组合多种实现,提供统一入口
     * org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator 将路由定义信息转化为路由
     * @author Spencer Gibb
     */
    // TODO: rename to Routes?
    public interface RouteLocator {
    
       Flux<Route> getRoutes();
    
    }
    

    GatewayAutoConfiguration 加载代码

    @Bean
    public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,
          List<GatewayFilterFactory> gatewayFilters,
          List<RoutePredicateFactory> predicates,
          RouteDefinitionLocator routeDefinitionLocator,
          ConfigurationService configurationService) {
       return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates,
             gatewayFilters, properties, configurationService);
    }
    
    @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
    package org.springframework.cloud.gateway.route;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import reactor.core.publisher.Flux;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.gateway.config.GatewayProperties;
    import org.springframework.cloud.gateway.event.FilterArgsEvent;
    import org.springframework.cloud.gateway.event.PredicateArgsEvent;
    import org.springframework.cloud.gateway.filter.FilterDefinition;
    import org.springframework.cloud.gateway.filter.GatewayFilter;
    import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
    import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory;
    import org.springframework.cloud.gateway.handler.AsyncPredicate;
    import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
    import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory;
    import org.springframework.cloud.gateway.support.ConfigurationService;
    import org.springframework.cloud.gateway.support.HasRouteId;
    import org.springframework.context.ApplicationEventPublisher;
    import org.springframework.context.ApplicationEventPublisherAware;
    import org.springframework.core.Ordered;
    import org.springframework.core.annotation.AnnotationAwareOrderComparator;
    import org.springframework.core.convert.ConversionService;
    import org.springframework.validation.Validator;
    import org.springframework.web.server.ServerWebExchange;
    
    /**
     * {@link RouteLocator} that loads routes from a {@link RouteDefinitionLocator}.
     *
     * @author Spencer Gibb
     */
    public class RouteDefinitionRouteLocator
    		implements RouteLocator, BeanFactoryAware, ApplicationEventPublisherAware {
    
    	/**
    	 * Default filters name.
    	 */
    	public static final String DEFAULT_FILTERS = "defaultFilters";
    
    	protected final Log logger = LogFactory.getLog(getClass());
         // 路由定义信息
    	private final RouteDefinitionLocator routeDefinitionLocator;
    
    	private final ConfigurationService configurationService;
        // 路由RoutePredicate工厂,配置该路由决定采取哪种路由规则,如何配置前缀就可以找到对应的实例??
    	private final Map<String, RoutePredicateFactory> predicates = new LinkedHashMap<>();
        // 路由GatewayFilter工厂,配置该路由决定走哪些过滤器,如何配置前缀就可以找到对应的实例??
    	private final Map<String, GatewayFilterFactory> gatewayFilterFactories = new HashMap<>();
    
    	private final GatewayProperties gatewayProperties;
    
    	@Deprecated
    	public RouteDefinitionRouteLocator(RouteDefinitionLocator routeDefinitionLocator,
    			List<RoutePredicateFactory> predicates,
    			List<GatewayFilterFactory> gatewayFilterFactories,
    			GatewayProperties gatewayProperties, ConversionService conversionService) {
    		this.routeDefinitionLocator = routeDefinitionLocator;
    		this.configurationService = new ConfigurationService();
    		this.configurationService.setConversionService(conversionService);
    		initFactories(predicates);
    		gatewayFilterFactories.forEach(
    				factory -> this.gatewayFilterFactories.put(factory.name(), factory));
    		this.gatewayProperties = gatewayProperties;
    	}
    
    	public RouteDefinitionRouteLocator(RouteDefinitionLocator routeDefinitionLocator,
    			List<RoutePredicateFactory> predicates,
    			List<GatewayFilterFactory> gatewayFilterFactories,
    			GatewayProperties gatewayProperties,
    			ConfigurationService configurationService) {
    		this.routeDefinitionLocator = routeDefinitionLocator;
    		this.configurationService = configurationService;
            // 配置前缀就可以找到对应的实例,将容器中的bean先放到内存
    		initFactories(predicates);
            // 配置前缀就可以找到对应的实例,将容器中的bean先放到内存
    		gatewayFilterFactories.forEach(
    				factory -> this.gatewayFilterFactories.put(factory.name(), factory));
    		this.gatewayProperties = gatewayProperties;
    	}
    
    	@Override
    	@Deprecated
    	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    		if (this.configurationService.getBeanFactory() == null) {
    			this.configurationService.setBeanFactory(beanFactory);
    		}
    	}
    
    	@Autowired
    	@Deprecated
    	public void setValidator(Validator validator) {
    		if (this.configurationService.getValidator() == null) {
    			this.configurationService.setValidator(validator);
    		}
    	}
    
    	@Override
    	@Deprecated
    	public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
    		if (this.configurationService.getPublisher() == null) {
    			this.configurationService.setApplicationEventPublisher(publisher);
    		}
    	}
    
        // 配置前缀就可以找到对应的实例,将容器中的bean先放到内存
    	private void initFactories(List<RoutePredicateFactory> predicates) {
    		predicates.forEach(factory -> {
    			String key = factory.name();
    			if (this.predicates.containsKey(key)) {
    				this.logger.warn("A RoutePredicateFactory named " + key
    						+ " already exists, class: " + this.predicates.get(key)
    						+ ". It will be overwritten.");
    			}
    			this.predicates.put(key, factory);
    			if (logger.isInfoEnabled()) {
    				logger.info("Loaded RoutePredicateFactory [" + key + "]");
    			}
    		});
    	}
    
    	@Override
    	public Flux<Route> getRoutes() {
            // 将路由定义信息转化成路由信息
    		Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions()
    				.map(this::convertToRoute);
    
    		if (!gatewayProperties.isFailOnRouteDefinitionError()) {
    			// instead of letting error bubble up, continue
    			routes = routes.onErrorContinue((error, obj) -> {
    				if (logger.isWarnEnabled()) {
    					logger.warn("RouteDefinition id " + ((RouteDefinition) obj).getId()
    							+ " will be ignored. Definition has invalid configs, "
    							+ error.getMessage());
    				}
    			});
    		}
    
    		return routes.map(route -> {
    			if (logger.isDebugEnabled()) {
    				logger.debug("RouteDefinition matched: " + route.getId());
    			}
    			return route;
    		});
    	}
         
        // 转换成路由信息
    	private Route convertToRoute(RouteDefinition routeDefinition) {
    		AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);
    		List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);
    
    		return Route.async(routeDefinition).asyncPredicate(predicate)
    				.replaceFilters(gatewayFilters).build();
    	}
    
    	@SuppressWarnings("unchecked")
        // 加载路由网关过滤器
    	List<GatewayFilter> loadGatewayFilters(String id,
    			List<FilterDefinition> filterDefinitions) {
    		ArrayList<GatewayFilter> ordered = new ArrayList<>(filterDefinitions.size());
    		for (int i = 0; i < filterDefinitions.size(); i++) {
    			FilterDefinition definition = filterDefinitions.get(i);
                // 获取网关过滤器工厂
    			GatewayFilterFactory factory = this.gatewayFilterFactories
    					.get(definition.getName());
    			if (factory == null) {
    				throw new IllegalArgumentException(
    						"Unable to find GatewayFilterFactory with name "
    								+ definition.getName());
    			}
    			if (logger.isDebugEnabled()) {
    				logger.debug("RouteDefinition " + id + " applying filter "
    						+ definition.getArgs() + " to " + definition.getName());
    			}
    
    			// @formatter:off
                // 构造每个工厂里对应的config信息
    			Object configuration = this.configurationService.with(factory)
    					.name(definition.getName())
    					.properties(definition.getArgs())
    					.eventFunction((bound, properties) -> new FilterArgsEvent(
    							// TODO: why explicit cast needed or java compile fails
    							RouteDefinitionRouteLocator.this, id, (Map<String, Object>) properties))
    					.bind();
    			// @formatter:on
    
    			// some filters require routeId
    			// TODO: is there a better place to apply this?
    			if (configuration instanceof HasRouteId) {
    				HasRouteId hasRouteId = (HasRouteId) configuration;
    				hasRouteId.setRouteId(id);
    			}
                 // 获取过滤器是实例
    			GatewayFilter gatewayFilter = factory.apply(configuration);
    			if (gatewayFilter instanceof Ordered) {
    				ordered.add(gatewayFilter);
    			}
    			else {
    				ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1));
    			}
    		}
    
    		return ordered;
    	}
        // 获取过滤器,并根据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,
    					new ArrayList<>(this.gatewayProperties.getDefaultFilters())));
    		}
    
    		if (!routeDefinition.getFilters().isEmpty()) {
    			filters.addAll(loadGatewayFilters(routeDefinition.getId(),
    					new ArrayList<>(routeDefinition.getFilters())));
    		}
    
    		AnnotationAwareOrderComparator.sort(filters);
    		return filters;
    	}
    
    	private AsyncPredicate<ServerWebExchange> combinePredicates(
    			RouteDefinition routeDefinition) {
    		List<PredicateDefinition> predicates = routeDefinition.getPredicates();
    		if (predicates == null || predicates.isEmpty()) {
    			// this is a very rare case, but possible, just match all
    			return AsyncPredicate.from(exchange -> true);
    		}
    		AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition,
    				predicates.get(0));
    
    		for (PredicateDefinition andPredicate : predicates.subList(1,
    				predicates.size())) {
    			AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition,
    					andPredicate);
    			predicate = predicate.and(found);
    		}
    
    		return predicate;
    	}
        //加载断言
    	@SuppressWarnings("unchecked")
    	private AsyncPredicate<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());
    		}
    		if (logger.isDebugEnabled()) {
    			logger.debug("RouteDefinition " + route.getId() + " applying "
    					+ predicate.getArgs() + " to " + predicate.getName());
    		}
    
    		// @formatter:off
    		Object config = this.configurationService.with(factory)
    				.name(predicate.getName())
    				.properties(predicate.getArgs())
    				.eventFunction((bound, properties) -> new PredicateArgsEvent(
    						RouteDefinitionRouteLocator.this, route.getId(), properties))
    				.bind();
    		// @formatter:on
             // 转换实例信息
    		return factory.applyAsync(config);
    	}
    
    }
    
    
    RouteDefinition路由定义

    SpringCloudGateway通过RouteDefinition来转换生成具体的路由信息。RouteDefinition的信息是怎么加载初始化到网关系统中的,主要是通过RouteDefinitionLocator(路由定义信息加载器)接口,实现RouteDefinition初始化加载

    • RouteDefinitionLocator源码
    /**
     * 路由定义信息的定位器,
     * 负责读取路由配置( org.springframework.cloud.gateway.route.RouteDefinition
     * 子类实现类
     *  1.CachingRouteDefinitionLocator -RouteDefinitionLocator包装类, 缓存目标RouteDefinitionLocator 为routeDefinitions提供缓存功能
     *  2.CompositeRouteDefinitionLocator -RouteDefinitionLocator包装类,组合多种 RouteDefinitionLocator 的实现,为 routeDefinitions提供统一入口
     *  3.PropertiesRouteDefinitionLocator-从配置文件(GatewayProperties 例如,YML / Properties 等 ) 读取RouteDefinition
     *  4.DiscoveryClientRouteDefinitionLocator-从注册中心( 例如,Eureka / Consul / Zookeeper / Etcd 等 )读取RouteDefinition
     *  5.RouteDefinitionRepository-从存储器( 例如,内存 / Redis / MySQL 等 )读取RouteDefinition
     * @author Spencer Gibb
     */
    public interface RouteDefinitionLocator {
    
        /**
         * 获取RouteDefinition
         * @return
         */
        Flux<RouteDefinition> getRouteDefinitions();
    }
    

    RouteDefinitionLocator接口有且仅有一个方法getRouteDefinitions,此方法获取RouteDefinition的核心方法,返回Flux

    RouteDefinitionLocator 类图如下:

    graph TD
    RouteDefinitionLocator-->CachingRouteDefinitionLocator
    RouteDefinitionLocator-->CompositeRouteDefinitionLocator
    RouteDefinitionLocator-->PropertiesRouteDefinitionLocator
    RouteDefinitionLocator-->DiscoveryClientRouteDefinitionLocator
    RouteDefinitionLocator-->RouteDefinitionRepository
    

    子类功能描述:

    • CachingRouteDefinitionLocator:RouteDefinitionLocator包装类, 缓存目标RouteDefinitionLocator 为routeDefinitions提供缓存功能
    • CompositeRouteDefinitionLocator -RouteDefinitionLocator包装类,组合多种 RouteDefinitionLocator 的实现,为 routeDefinitions提供统一入口
    • PropertiesRouteDefinitionLocator-从配置文件(GatewayProperties 例如,YML / Properties 等 ) 读取RouteDefinition
    • RouteDefinitionRepository-从存储器( 例如,内存 / Redis / MySQL 等 )读取RouteDefinition
    • DiscoveryClientRouteDefinitionLocator-从注册中心( 例如,Eureka / Consul / Zookeeper / Etcd 等
    • PropertiesRouteDefinitionLocator
    /**
     * 从Properties(GatewayProperties)中加载RouteDefinition信息
     * @author Spencer Gibb
     */
    public class PropertiesRouteDefinitionLocator implements RouteDefinitionLocator {
    
        /**
         * 从appliccation.yml中解析前缀为spring.cloud.gateway的配置
         */
        private final GatewayProperties properties;
    
        public PropertiesRouteDefinitionLocator(GatewayProperties properties) {
            this.properties = properties;
        }
    
        @Override
        public Flux<RouteDefinition> getRouteDefinitions() {
            return Flux.fromIterable(this.properties.getRoutes());
        }
    }
    

    PropertiesRouteDefinitionLocator很简单从GatewayProperties实例获取RouteDefinition信息

    • GatewayProperties 在GatewayProperties初始化加载文中已详细描述
    • Flux 响应式编程
    • CachingRouteDefinitionLocator
    /**
     * RouteDefinitionLocator 包装实现类,实现了路由定义的本地缓存功能
     * @author Spencer Gibb
     */
    public class CachingRouteDefinitionLocator implements RouteDefinitionLocator {
    
        /**
         * 实际路由定义定位器
         */
        private final RouteDefinitionLocator delegate;
        
        private final Flux<RouteDefinition> routeDefinitions;
        /**
         * 路由定义的本地缓存
         */
        private final Map<String, List> cache = new HashMap<>();
    
        public CachingRouteDefinitionLocator(RouteDefinitionLocator delegate) {
            this.delegate = delegate;
            routeDefinitions = CacheFlux.lookup(cache, "routeDefs", RouteDefinition.class)
                    .onCacheMissResume(() -> this.delegate.getRouteDefinitions());
    
        }
    
    }   
    

    RouteDefinitionLocator包装类,缓存目标RouteDefinitionLocator 为routeDefinitions提供缓存功能

    • DiscoveryClientRouteDefinitionLocator
    public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLocator {
        /**
         * 注册中心客户端
         */
        private final DiscoveryClient discoveryClient;
        /**
         * 本地配置信息
         */
        private final DiscoveryLocatorProperties properties;
        /**
         * 路由ID前缀
         */
        private final String routeIdPrefix;
    
        public DiscoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) {
            this.discoveryClient = discoveryClient;
            this.properties = properties;
            if (StringUtils.hasText(properties.getRouteIdPrefix())) {
                this.routeIdPrefix = properties.getRouteIdPrefix();
            } else {
                this.routeIdPrefix = this.discoveryClient.getClass().getSimpleName() + "_";
            }
        }
    
        /**
         * 通过注册中心查找服务组装路由定义信息
         * @return
         */
        @Override
        public Flux<RouteDefinition> getRouteDefinitions() {
         ...代码在根据注册中心查找路由详细解析
    
        }
    }   
    

    DiscoveryClientRouteDefinitionLocator通过调用 DiscoveryClient 获取注册在注册中心的服务列表,生成对应的 RouteDefinition 数组

    • CompositeRouteDefinitionLocator
    /**
     * 组合多个 RouteDefinitionLocator 的实现,为 routeDefinitions提供统一入口
     * @author Spencer Gibb
     */
    public class CompositeRouteDefinitionLocator implements RouteDefinitionLocator {
    
        /**
         * 所有路由定义定位器实例集合
         */
        private final Flux<RouteDefinitionLocator> delegates;
    
        public CompositeRouteDefinitionLocator(Flux<RouteDefinitionLocator> delegates) {
            this.delegates = delegates;
        }
    
        @Override
        public Flux<RouteDefinition> getRouteDefinitions() {
            //将各个RouteDefinitionLocator的getRouteDefinitions合并返回统一的Flux<RouteDefinition>
            return this.delegates.flatMap(RouteDefinitionLocator::getRouteDefinitions);
        }
    }
    

    CompositeRouteDefinitionLocator 的主要作用就是将各个定位器合并提供统一的getRouteDefinitions方法入口

    通过子类实现具体功能可以很清晰的看到定位器加载RouteDefinition整个流程

    graph TD
    PropertiesRouteDefinitionLocator-->|配置文件加载初始化| CompositeRouteDefinitionLocator
    RouteDefinitionRepository-->|存储器中加载初始化| CompositeRouteDefinitionLocator
    DiscoveryClientRouteDefinitionLocator-->|注册中心加载初始化| CompositeRouteDefinitionLocator
    

    最终提供通过CompositeRouteDefinitionLocator提供统一的 getRouteDefinitions方法

    RouteDefinitionLocator实例的初始化在GatewayAutoConfiguration中已经完成

    • GatewayDiscoveryClientAutoConfiguration
    @Configuration
    @ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
    @AutoConfigureBefore(GatewayAutoConfiguration.class)
    @ConditionalOnClass({DispatcherHandler.class, DiscoveryClient.class})
    @EnableConfigurationProperties
    public class GatewayDiscoveryClientAutoConfiguration {
    
        //初始化注册中心路由定义定位器
        @Bean
        @ConditionalOnBean(DiscoveryClient.class)
        @ConditionalOnProperty(name = "spring.cloud.gateway.discovery.locator.enabled")
        public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(
                DiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) {
            return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties);
        }
    
    • GatewayAutoConfiguration
       //初始化配置路由定义加载器
        @Bean
        @ConditionalOnMissingBean
        public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) {
            return new PropertiesRouteDefinitionLocator(properties);
        }
    
        //初始化存储路由定义加载器
        @Bean
        @ConditionalOnMissingBean(RouteDefinitionRepository.class)
        public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() {
            return new InMemoryRouteDefinitionRepository();
        }
    
         //初始化聚合路由定义加载器
        @Bean
        @Primary
        public RouteDefinitionLocator routeDefinitionLocator(List<RouteDefinitionLocator> routeDefinitionLocators) {
            return new CompositeRouteDefinitionLocator(Flux.fromIterable(routeDefinitionLocators));
        }
    

    在Spring-Cloud-Gateway初始化完成后需要的路由定义加载器已全部实例化完成,这样就为路由的加载创建完成了必要的条件。

    展开全文
  • 动态路由协议(动态路由和rip) 动态路由协议通过路由信息的交换生成并维护转发引擎所需的路由表。...文章目录动态路由协议(动态路由和rip)动态路由动态路由概述动态路由协议基础动态路由协议分类rip路由协议rip路由

    动态路由协议(动态路由和rip)

    动态路由协议通过路由信息的交换生成并维护转发引擎所需的路由表。当网络拓扑结构改变时动态路由协议可以自动更新路由表,并负责决定数据传输最佳路径。
    在动态路由中,管理员不再需要与静态路由一样,手工对路由器上的路由表进行维护,而是在每台路由器上运行一个路由协议。这个路由协议会根据路由器上的接口的配置(如IP地址的配置)及所连接的链路的状态,生成路由表中的路由表项。

    动态路由

    路由行为指的是,当网络设备收到一个IP报文时,会在自己的路由表(Routing-table)中查询报文的目的IP地址,如果能够找到匹配给目的IP地址的路由表项,则根据该表项所指示的下一跳及出接口转发报文;如果没有任何路由表项匹配,则丢弃该报文。
    路由的行为是逐跳的,因此报文从源去往目的地的过程中,沿途的每一个参与数据转发的网络设备都需要具有关于目的网络的路由。

    动态路由概述

    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述动态路由
    基于某种路由协议实现

    动态路由特点

    • 减少了管理任务
    • 占用了网络带宽

    查看路由表

    display ip routing-table
    

    动态路由协议基础

    动态路由协议概述
    路由器之间用来交换信息的语言

    度量值
    跳数、带宽、负载、时延、可靠性、成本
    跳数指的是去往目标网络所需要经过的路由器个数。

    在这里插入图片描述

    收敛
    使所有路由器都达到一致状态的过程

    静态路由和动态路由的比较
    网络中静态路由和动态路由互相补充

    动态路由协议分类

    按照路由执行的算法分类
    距离矢量路由协议
    依据从源网络到目标网络所经过的路由器的个数选择路由
    RIP、IGRP

    链路状态路由协议
    综合考虑从源网络到目标网络的各条路径的情况选择路由
    OSPF、IS-IS

    在这里插入图片描述

    rip路由协议

    RIP(Routing Information Protocols,路由信息协议)。
    是应用较早的内部网关协议(IGP)。

    RIP是距离矢量路由选择协议
    适用于小型网络,是典型的距离矢量协议。
    RIP基于UDP,端口520。
    路由优先级为100。
    RIP有三个版本:RIPv1、RIPv2及RIPng。

    rip路由协议的工作原理

    RIP的基本概念
    定期更新(路由每经过一个指定的时间周期,向其他邻居发送更新信息。因此距离矢量路由协议更新方式也被称为‘逐跳’更新,在RFC2453文档中把RIP的更新时间定义为30S)

    邻居(与其相连的路由器)在距离矢量具有协议中,可以额理解与其直接相连的路由器

    广播更新(Ripv1 255.255.255.255)

    组播更新(Ripv2 224.0.0.9)

    泛洪路由表(路由器将从邻居学习到的路由放进自己的路由表中,然后将路由表所有路由信息在通告给其他路由器,直到整个网络学习到)

    Metric:也称为度量值,RIP协议以Hop(跳数)作为度量值,每经过一台设备被视为1跳,RIP协议最大跳数15跳,而16跳是一个无穷大的值,如果为该值,可视为不可达

    最大跳数的设定虽然解决了度量值技术到无穷大的问题,但是却也极大地限制了RIP所能支持的网络的规模。

    RIPv1报文格式
    在这里插入图片描述RIPv2报文格式
    在这里插入图片描述区别:
    1.RIP1是一个有类路由协议,即所有的更新包中不含子网掩码,不支持VLSM,
    所以就要求网络中所有设备必须使用相同的子网掩码,否则就会出错,
    而RIP2是一个无类的路由协议,它使用子网掩码。

    2.第二个不同的地方是RIP1是发送更新包的时候使用的是广播包,
    而RIP2默认使用的是组播224.0.0.9,也支持广播发送,
    这样相对于RIP1来说就节省了一部分网络带宽。

    3.第三个就是RIP2支持明文或者是 MD5验证,要求两台路由器在同步路由表的时候必须进行验证,
    通过才可以进行路由同步,这样可以加强安全性。

    rip路由协议的配置

    rip 1   ###起rip进程
    version 2    ###开启RIP 2版本
    network  网络号  ###把要宣告的网段说出去  2个路由器的网段必须要宣告,否则不能建立关系
    

    例如:
    在这里插入图片描述

    rip 1
    version 2
    network 192.168.1.0
    network 192.168.12.0
    
    展开全文
  • 动态路由动态路由中的RIP协议一.动态路由1.动态路由的特点2.选择依据:度量值3.收敛4.静态路由与动态路由的比较二.动态路由协议分类三.RIP是距离矢量路由选择协议1.RIP的基本概念2.RIP的度量值与更新时间四.RIP...

    一.动态路由

    动态路由:路由器之间用来交换信息的语言,基于某种路由协议实现。

    1.动态路由的特点

    1.减少了网络管理
    2.占用了网络带宽

    2.选择依据:度量值

    跳数、带宽、负载、时延、可靠性、成本
    路由器会通过度量值来确定最优路由路径

    3.收敛

    使所有路由器都到达一致状态的过程

    4.静态路由与动态路由的比较

    网络中静态路由和动态路由相互补充

    二.动态路由协议分类

    距离矢量路由协议
    ——依据从源网络到目标网络所经过的路由器的个数选择路由 - - RIP、IGIP(思科私有协议)
    链路状态路由协议
    ——综合考虑从源网络到目标网络的各条路径的情况选择路由 - - OSPF、ISIS

    三.RIP是距离矢量路由选择协议

    1.RIP的基本概念

    ①定期更新 30s
    ②邻居
    ③广播更新RIPV1:255.255.255.255
    组播更新RIPV2:224.0.0.9
    ④全路由更新

    2.RIP的度量值与更新时间

    RIP度量值为跳数
    最大跳数为15跳,16跳为不可达

    RIP更新时间
    每隔30s发送路由更新消息,UDP520端口

    RIP路由更新消息
    发送整个路由表信息

    四.RIP协议防环机制

    路由毒化
    当路由器发现路由链路进行变更或者down掉后,会将这个路由毒化,标志为16跳,不可达

    水平分割
    水平分割可以阻止路由环路的发生
    从一个接口学习到路由信息,不再从这个接口发送回去,同时也能减少路由更新信息占用的链路带宽资源

    五.RIPV1和RIPV2的区别

    在这里插入图片描述

    六.RIP命令

    【R1】rip 1 启动RIP
    【R1 - rip - 1】network x.x.x.x
    【R1 - rip - 1】network x.x.x.x
    【R1 - rip - 1】version 2 启动版本2
    【R1 - rip - 1】undo summary 关闭路由自动聚

    展开全文
  • 一、路由算法、 二、路由算法 分类、 三、静态路由算法、 四、动态路由算法、 五、动态路由算法 分类、 六、分层次的路由选择协议、
  • 整个动态路由的设置是我自己研究写的,现在项目中没发现什么问题。如发现有问题,欢迎前来纠正,谢谢!!! 链接:https://pan.baidu.com/s/1J9R2TkqJk0H9JMjqp2WcFw 提取码:n4rk 复制这段内容后打开百度网盘手机...
  • 路由协议有静态和动态协议两种,动态路由跟静态路由是相对的,我们今天就来看看动态路由协议是什么,有什么特点!动态路由协议,就是路由器能够自己建立路由表,不需要管理员手动一条一条将路由加表,这样就节省了...
  • 动态路由浅析

    2020-11-03 14:30:33
    动态路由浅析一、动态路由概述1.1动态路由1.2特点1.3动态路由协议概述1.4度量值1.5收敛1.6静态路由与动态路由的比较二、动态路由协议分类2.1按照路由执行的算法分类三、 RIP路由协议工作原理3.1、RIP是距离-----矢量...
  • 初始动态路由

    2021-02-14 19:16:47
    目录动态路由协议动、静态路由的对比衡量动态路由好坏的标准动态路由协议的分类: 动态路由协议 动态路由—各台路由器之间运行了一定的算法,相互学习沟通产生路由条目 作用: 解决未知网段问题 动、静态路由的对比 ...
  • 动态路由的优点 1.配置管理方便 2.适用于中大型网络 3.针对拓扑的变化可以自动重新收敛 动态路由协议的缺点 1.安全 2.容易造成选路不佳-最严重的情况—环路 3.占用硬件资源 衡量动态路由协议好坏的标准 pre 1.选路佳...
  • 动态路由协议

    2020-11-03 19:22:33
    这里写目录标题动态路由协议动态路由动态路由的特点动态路由协议概述度量值收敛静态路由与动态路由的比较按照路由执行的算法分类RIP路由协议工作原理RIP的基本概念路由表的形成三级目录 动态路由协议 动态路由 基于...
  • RIP动态路由

    2021-01-07 18:27:33
    目录标题动态路由协议动态路由协议分类RIP路由协议路由表的形成RIP的度量值与更新时间水平分割RIPv1和RIPv2的区别执行水平分割阻止环路RIP配置 动态路由协议 动态路由: 基于某种路由协议实现 动态路由的特点: 1....
  • 静态路由和动态路由

    万次阅读 多人点赞 2018-12-23 16:50:31
    (3)掌握动态路由的配置。   实验要求: (1)写出静态路由的配置过程; (2)写出动态路由的配置过程。   一、路由器的作用  所谓“路由”,是指把...
  • 动态路由RIP

    2020-03-06 21:07:50
    动态路由之RIP 一、 动态路由概述 动态路由可以实现路由器之间动态的互相学习路由表,而不需要工程师手动写路由。 二、 动态路由协议 动态路由基于一种动态路由协议实现的。 协议:就是一种设备之间的语言或规则。如...
  • 动态路由简述: 1、动态路由是与静态路由相对的一个概念,指路由器能够根据路由器之间的交换的特定路由信息自动地建立自己的路由表,并且能够根据链路和节点的变化适时地进行自动调整2、当网络中节点或节点间的链路...
  • 动态路由与静态路由

    2019-10-05 01:18:08
    动态路由协仪 动态路由协议通过路由信息的交换生成并维护转发引擎所需的路由表。当网络拓扑结构改变时动态路由协议可以自动更新路由表,并负责决定数据传输最佳路径。 作用 动态路由协议的作用主要有以下三点: (1)...
  • 动态路由心得

    2020-02-25 12:09:06
    动态路由 1.动态路由概念 1)动态路由是网络中的路由器之间自动互相通信,传递路由信息,不用人工干预,利用收到的路由信息定时更新路由器表的过程。动态路由要比使用静态路由和默认路由配置简单但是需要消耗路由器...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 17,810
精华内容 7,124
关键字:

动态路由