网关 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 注


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

查看所有标签

猜你喜欢:

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

Learning Web App Development

Learning Web App Development

Semmy Purewal / O'Reilly Media / 2014-3-3 / USD 29.99

Grasp the fundamentals of web application development by building a simple database-backed app from scratch, using HTML, JavaScript, and other open source tools. Through hands-on tutorials, this pract......一起来看看 《Learning Web App Development》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具