网关 Spring-Cloud-Gateway 源码解析 —— 路由(1.4)之 DiscoveryClientRouteDefinitionLocator 注

栏目: Java · 发布时间: 6年前

内容简介:网关 Spring-Cloud-Gateway 源码解析 —— 路由(1.4)之 DiscoveryClientRouteDefinitionLocator 注

摘要: 原创出处 http://www.iocoder.cn/Spring-Cloud-Gateway/route-definition-locator-discover-client/ 「芋道源码」欢迎转载,保留摘要,谢谢!

本文主要基于 Spring-Cloud-Gateway 2.0.X M4

网关 Spring-Cloud-Gateway 源码解析 —— 路由(1.4)之 DiscoveryClientRouteDefinitionLocator 注

关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有 源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言 将得到 认真 回复。 甚至不知道如何读源码也可以请教噢
  4. 新的 源码解析文章 实时 收到通知。 每周更新一篇左右
  5. 认真的 源码交流微信群。

1. 概述

本文主要对 DiscoveryClientRouteDefinitionLocator 的源码实现

DiscoveryClientRouteDefinitionLocator 通过调用 org.springframework.cloud.client.discovery.DiscoveryClient 获取注册在注册中心的服务列表,生成对应的 RouteDefinition 数组。

推荐 Spring Cloud 书籍:

2. 环境搭建

在解析源码之前,我们先以 Eureka 为注册中心,讲解下如何配置 DiscoveryClientRouteDefinitionLocator 。

第一步,以 spring-cloud-gateway-sample 项目为基础,在 pom.xml 文件添加依赖库。

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-eureka</artifactId>
 <version>2.0.0.M1</version>
 <exclusions>
 <exclusion>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </exclusion>
 </exclusions>
</dependency>
  • 注意,需要排除 spring-boot-starter-web 的依赖,避免和 Spring Cloud Gateway 依赖的 spring-boot-starter-webflux 冲突。

第二步,在 application.yml 添加 Eureka 相关配置 。

spring:
application:
name: juejin-gateway

eureka:
instance:
leaseRenewalIntervalInSeconds: 10
leaseExpirationDurationInSeconds: 30
client:
serviceUrl:
defaultZone: http://eureka.didispace.com/eureka/

第三步,在 org.springframework.cloud.gateway.sample.GatewaySampleApplication 里,添加 RouteDefinitionLocator Bean 配置。

@EnableDiscoveryClient // {@link DiscoveryClientRouteDefinitionLocator}
public class GatewaySampleApplication{
 
 // ... 省略其他代码

 @Bean
 public RouteDefinitionLocator discoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient){
 return new DiscoveryClientRouteDefinitionLocator(discoveryClient);
 }
}

第四步,启动一个注册在 Eureka 的应用服务。机智如你,这里我就不啰嗦落。

第五步,在 DiscoveryClientRouteDefinitionLocator 的 #getRouteDefinitions() 方法打 断点 ,调试启动 spring-cloud-gateway-sample 。小功告成。撒花~

3. DiscoveryClientRouteDefinitionLocator

org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator ,通过调用 DiscoveryClient 获取注册在注册中心的服务列表,生成对应的 RouteDefinition 数组。

代码如下 :

 1: public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLocator{
 2: 
 3: private final DiscoveryClient discoveryClient;
 4: private final String routeIdPrefix;
 5: 
 6: public DiscoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient){
 7: this.discoveryClient = discoveryClient;
 8: this.routeIdPrefix = this.discoveryClient.getClass().getSimpleName() + "_";
 9: }
10: 
11: @Override
12: public Flux<RouteDefinition> getRouteDefinitions(){
13: return Flux.fromIterable(discoveryClient.getServices())
14: .map(serviceId -> {
15: RouteDefinition routeDefinition = new RouteDefinition();
16: // 设置 ID
17: routeDefinition.setId(this.routeIdPrefix + serviceId);
18: // 设置 URI
19: routeDefinition.setUri(URI.create("lb://" + serviceId));
20: 
21: // add a predicate that matches the url at /serviceId
22: /*PredicateDefinition barePredicate = new PredicateDefinition();
23: barePredicate.setName(normalizePredicateName(PathRoutePredicateFactory.class));
24: barePredicate.addArg(PATTERN_KEY, "/" + serviceId);
25: routeDefinition.getPredicates().add(barePredicate);*/
26: 
27: // 添加 Path 匹配断言
28: // add a predicate that matches the url at /serviceId/**
29: PredicateDefinition subPredicate = new PredicateDefinition();
30: subPredicate.setName(normalizePredicateName(PathRoutePredicateFactory.class));
31: subPredicate.addArg(PATTERN_KEY, "/" + serviceId + "/**");
32: routeDefinition.getPredicates().add(subPredicate);
33: 
34: //TODO: support for other default predicates
35: 
36: // 添加 Path 重写过滤器
37: // add a filter that removes /serviceId by default
38: FilterDefinition filter = new FilterDefinition();
39: filter.setName(normalizeFilterName(RewritePathGatewayFilterFactory.class));
40: String regex = "/" + serviceId + "/(?<remaining>.*)";
41: String replacement = "/${remaining}";
42: filter.addArg(REGEXP_KEY, regex);
43: filter.addArg(REPLACEMENT_KEY, replacement);
44: routeDefinition.getFilters().add(filter);
45: 
46: //TODO: support for default filters
47: 
48: return routeDefinition;
49: });
50: }
51: }

4. 高能

本小节建议阅读完 《Spring-Cloud-Gateway 源码解析 —— 路由(2.1)之 RouteLocator 一览》 再理解。

RoutePredicateHandlerMapping 使用 CachingRouteLocator 来获取 Route 信息。在 Spring Cloud Gateway 启动后,如果有新加入的服务,则需要刷新 CachingRouteLocator 缓存

这里有一点需要 注意 下 :新加入的服务,指的是新的 serviceId ,而不是原有服务新增的实例。

个人建议,写一个定时任务,间隔调用 DiscoveryClient 获取服务列表,若发现 变化 ,刷新 CachingRouteLocator 缓存

666. 彩蛋

:smiling_imp: 满足。主要因为这小节,原来还是非常担心服务列表的缓存与刷新问题,如果不解决,网关基本属于不可用的状态。

网关 Spring-Cloud-Gateway 源码解析 —— 路由(1.4)之 DiscoveryClientRouteDefinitionLocator 注


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Two Scoops of Django

Two Scoops of Django

Daniel Greenfeld、Audrey M. Roy / CreateSpace Independent Publishing Platform / 2013-4-16 / USD 29.95

Two Scoops of Django: Best Practices For Django 1.5 is chock-full of material that will help you with your Django projects. We'll introduce you to various tips, tricks, patterns, code snippets, and......一起来看看 《Two Scoops of Django》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

html转js在线工具
html转js在线工具

html转js在线工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试