Spring Cloud Gateway结合注册中心使用,自定义路由功能

原创 吴就业 132 0 2020-08-22

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://www.wujiuye.com/article/cb5507b385a24a9d99e3d547870c8d51

作者:吴就业
链接:https://www.wujiuye.com/article/cb5507b385a24a9d99e3d547870c8d51
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

本篇文章写于2020年08月22日,从公众号|掘金|CSDN手工同步过来(博客搬家),本篇为原创文章。

Spring Cloud Kubernetes微服务实战与源码分析

使用API网关可统一流量入口,对客户端屏蔽内部多个微服务的域名,实现负载均衡,并可以统一鉴权、接口访问控制、流量管控。

作为网关,代理了所有流量,对性能要求更高,介于网关核心功能是路由、代理后端服务,主要处理请求转发,如果使用同步阻塞方式,后端接口响应耗时越长,对网关性能的影响就越大。nginx作为反向代理中的佼佼者,基于nginx开发的Kong网关性能更是毋庸置疑。但作为内部网关,我们需要更好的定制,选择Java系的网关对我们来说更容易驾驭。

在选定编程语言后,我们就需要考虑性能问题。而网关的性能损耗无非就是I/O阻塞,只有纯异步才能有更好的性能表现,所以我们选择至少是基于实现Reactive Streams规范的反应式编程库开发的网关。

Spring cloud gateway作为spring cloud生态系统中的网关,基于Spring Boot、Project Reactor开发,不仅实现异步非阻塞,并且更快速与spring cloud生态中的其它组件整合,这是我们选择Spring cloud gateway的原因。

我们基于Spring Cloud Gateway开发内部微服务网关,并结合注册中心实现自动服务发现路由。

就在最近将项目部署测试环境的Kubernetes集群上时,发现路由失败。经调试源码发现是因为没有导入Ribbon的依赖,所以Gateway注册的是非负载均衡路由过滤器(NoLoadBalancerClientFilter),当路由规则配置以”lb://“开头时,该路由过滤器直接响应503(目标服务不可达)。

Gateway使用全局过滤器实现路由功能,其按照全局过滤器指定的排序值顺序调用,每个过滤器都可终止请求的调用。

Gateway允许每个全局过滤器重写路由URL,通过将重写后的URL更新到请求的attribute向下传递,下游过滤器可重新修改路由URL,最初的路由URL从路由规则取得。

// 从ServerWebExchange#getAttribute取得路由url
URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);

Gateway使用一个链表将每个过滤器替换前的路由URL串起来,如果想获取URL被替换为目标服务URL过程的变化,可获取该链表、遍历该链表。

// 记录修改前的url
addOriginalRequestUrl(exchange, url);
// 
public static void addOriginalRequestUrl(ServerWebExchange exchange, URI url) {
    exchange.getAttributes().computeIfAbsent(GATEWAY_ORIGINAL_REQUEST_URL_ATTR,
        s -> new LinkedHashSet<>());
    LinkedHashSet<URI> uris = exchange
        .getRequiredAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
    uris.add(url);
}

Gateway接收到一个请求后,请求从FilteringWebHandler传送到全局过滤器链上(GatewayFilterChain),在过滤器链上向下传递,经过中间过滤器将请求URL替换后,由最后的请求转发过滤器(ForwardRoutingFilter)将请求交给DispatcherHandler向目标服务发起请求并将结果响应给调用端。

img

在了解路由失效的原因后、在尝试依赖Ribbon的starter包依然路由失败后,笔者决定自己实现路由功能,并使用Ribbon实现的负载均衡算法在网关实现负载均衡。

由于项目是基于Spring Cloud Kubernetes开发的微服务项目,使用Kubernetes云原生服务作为“注册中心”,服务无需注册,可通过kubernete API读取Service或Endpoints资源,并且spring-cloud-kubernete-core提供了读取Service或Endpoints资源的API,因此自己实现路由功能相比于依赖一堆无关紧要的jar包更轻量。

负载均衡功能是次要的,如果不需要在网关实现负载均衡,则可以将服务发现模式改为Service,读取Kubernetes中的Service资源的Cluster IP;如果想要在网关实现负载均衡,而可以将服务发现模式改为Pod,读取Kubernetes的Endpoints资源。

自实现路由功能分为以下几个步骤:

img

#后端

声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。

文章推荐

设计模式那些模糊不清的概念

23种设计模式属于结构型模式,而mvc模式等属于架构型模式。本篇要讨论的设计模式指的是结构型设计模式。

实现一个分布式调用链路追踪Java探针你可能会遇到的问题

Instrumentation之所以难驾驭,在于需要了解Java类加载机制以及字节码,一不小心就能遇到各种陌生的Exception。笔者在实现Java探针时就踩过不少坑,其中一类就是类加载相关的问题,也是本篇所要跟大家分享的。

从HotSpot虚拟机源码了解Java的访问控制修饰符

类、字段、方法都有哪些访问控制修饰符? 今天我们就深入java虚拟机去探究这些访问控制修饰符语意的实现。

Sentinel与OpenFeign整合实现熔断降级源码分析

本篇我们从源码分析Sentinel与OpenFeign整合实现熔断降级的原理。

OpenFeign整合Sentinel实现熔断降级

本篇先介绍如何将Sentinel与OpenFeign整合使用,并且熔断降级策略使用动态配置,将配置存储在配置中心。

玩转OpenFeign(下)

这篇主要介绍如何为不同的Client配置不同的连接超时、读超时这类参数,并从源码角度分析配置是怎么起作用的,以及都可以配置哪些参数,内容不多。