终身学习、乐于分享、共同成长!
前言
随着微服务架构的流行,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去用。
这样的架构,会存在着诸多的问题:
- 每个业务都会需要鉴权、限流、权限校验、跨域等逻辑,如果每个业务都各自为战,自己造轮子实现一遍,会很蛋疼,完全可以抽出来,放到一个统一的地方去做。
- 如果业务量比较简单的话,这种方式前期不会有什么问题,但随着业务越来越复杂,比如淘宝打开一个页面可能会涉及到数百个微服务协同工作,如果每一个微服务都分配一个域名的话,一方面客户端代码会很难维护,涉及到数百个域名,另一方面是连接数的瓶颈,想象一下你打开一个APP,通过抓包发现涉及到了数百个远程调用,这在移动端下会显得非常低效。
- 后期如果需要对微服务进行重构的话,也会变的非常麻烦,需要客户端配合你一起进行改造,比如商品服务,随着业务变的越来越复杂,后期需要进行拆分成多个微服务,这个时候对外提供的服务也需要拆分成多个,同时需要客户端配合你进行改造,非常蛋疼。
上面的这些问题可以借助API网关来解决。
所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、路由转发等等。
添加API网关之后,系统的架构图变成了如下所示:
加上网关之后的微服务整体架构图
Spring Cloud Gateway
Spring Cloud Gateway 是Spring Cloud生态系统中的微服务网关解决方案,它基于Spring5、Spring Boot2和Project Reactor等技术栈,提供了一种简单而有效的方式来让请求流量转发到一个或多个后端服务。
Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,定位于取代 Netflix Zuul1.0。相比 Zuul 来说,Spring Cloud Gateway 提供更优秀的性能,更强大的有功能。
Spring Cloud Gateway是由WebFlux + Netty + Reactor实现的响应式的API网关。它不能在传统的 servlet 容器中工作,也不能构建成 war 包。
Spring Cloud Gateway 旨在为微服务架构提供一种简单且有效的 API 路由的管理方式,并基于 Filter 的方式提供网关的基本功能,例如说安全认证、监控、限流等等。
Spring Cloud Gateway 具有以下主要特性:
- 基于路由的请求转发:Spring Cloud Gateway 可以通过预定义的路由规则将请求转发到不同的后端服务,从而实现负载均衡、熔断降级等功能。
- 过滤器链:Spring Cloud Gateway 的过滤器链可以对请求进行多次处理,比如添加请求头、修改请求体、验证参数等操作。
- 支持非阻塞式 I/O 模型:Spring Cloud Gateway 基于 Reactor 提供了响应式编程模型,能够更好地支持高并发、低延迟的场景。
- 高度可扩展:Spring Cloud Gateway 的路由规则和过滤器链都是基于 Java 代码实现的,因此可以很容易地进行扩展和定制。
官方文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html
核心概念
- 路由(route)
路由是网关中最基础的部分,路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。如果断言为真,则说明请求的URL和配置的路由匹配。
- 断言(predicates)
Java8中的断言函数,SpringCloud Gateway中的断言函数类型是Spring5.0框架中的ServerWebExchange。断言函数允许开发者去定义匹配Http request中的任何信息,比如请求头和参数等。
- 过滤器(Filter)
SpringCloud Gateway中的filter分为Gateway FilIer和Global Filter。Filter可以对请求和响应进行处理。
工作原理
执行流程大致如下:
- Gateway Client向Gateway Server发送请求
- 请求首先会被HttpWebHandlerAdapter进行提取组装成网关上下文
- 然后网关的上下文会传递到DispatcherHandler,它负责将请求分发给RoutePredicateHandlerMapping
- RoutePredicateHandlerMapping负责路由查找,并根据路由断言判断路由是否可用
- 如果过断言成功,由FilteringWebHandler创建过滤器链并调用
- 请求会一次经过PreFilter--微服务--PostFilter的方法,最终返回响应
快速入门
下面通过一个简单的示例来演示 Spring Cloud Gateway 的用法。
- 首先,在pom.xml中添加以下依赖项:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
- 然后,在bootstrap.yml中配置路由规则和过滤器链:
spring:
application:
name: gateway-server
cloud:
gateway:
routes:
- id: order-server # 当前路由的标识,要求唯一
uri: http://localhost:8008 # 请求要转发到的地址
order: 1 # 路由的优先级,数值越小,优先级越高
predicates: # 断言(就是指路由转发需要满足的条件)
- Path=/order-server/** # 当请求路径满足Path指定的路径时,才进行路由转发
filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
- StripPrefix=1 # 转发之前去掉1层路径
- 集成Nacos
现在是在配置文件中写死了转发地址,这样非常不灵活,也难以维护,接下来通过注册中心获取服务名称进行路由转发。
首先引入Nacos服务注册与发现依赖
<!--nacos-服务注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
然后修改bootstrap.yml配置文件的路由模式
spring:
application:
name: gateway-server # 应用名称 (nacos会将该名称当做服务名称)
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml # 基于 dataId 为 yaml 的文件扩展名配置方式
#namespace: d8f2135d-4ed8-42e4-8842-cdea14152b02 # 指定命名空间
#group: DEVELOP_GROUP
discovery:
server-addr: 127.0.0.1:8848
gateway:
routes:
- id: order-server # 当前路由的标识,要求唯一
uri: lb://order-server # 请求要转发到的地址,lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
order: 1 # 路由的优先级,数值越小,优先级越高
predicates: # 断言(就是指路由转发需要满足的条件)
- Path=/order-server/** # 当请求路径满足Path指定的路径时,才进行路由转发
filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
- StripPrefix=1 # 转发之前去掉1层路径
总结
- Spring Cloud Gateway 是Spring Cloud生态系统中的微服务网关解决方案,它基于Spring5、Spring Boot2和Project Reactor等技术栈,提供了一种简单而有效的方式来让请求流量转发到一个或多个后端服务。
- Spring Cloud Gateway是由WebFlux + Netty + Reactor实现的响应式的API网关。它不能在传统的 servlet 容器中工作,也不能构建成 war 包。
- 最后通过一个例子快速入门体验网关的使用。
完整代码可以在公众号Seven的代码实验室中回复SpringCloudAlibaba获取。
我是Seven,一个不懈努力的程序猿,希望本文能对你有所裨益