一个系统会被拆分为多个微服务,作为客户端要如何去调用这么多的微服务?如果没有网关的存在,只能在客户端记录每个微服务的地址,然后分别去调用。
例如下图:
这样的架构,会存在着诸多的问题:
·每个业务都会需要鉴权、限流、权限校验、跨域等逻辑,如果每个业务都各自为战,自己造轮子实现一遍,完全可以抽出来,放到一个统一的地方去做。
·如果业务量比较简单的话,这种方式前期不会有什么问题,但随着业务越来越复杂,比如淘宝、亚马逊打开一个页面可能会涉及到数百个微服务协同工作,如果每一个微服务都分配一个域名的话,一方面客户端代码会很难维护,涉及到数百个域名,另一方面是连接数的瓶颈,通过抓包发现涉及到了数百个远程调用,这在移动端下会显得非常低效。
后期如果需要对微服务进行重构的话,也会变的非常麻烦,需要客户端配合你一起进行改造,比如商品服务,随着业务变的越来越复杂,后期需要进行拆分成多个微服务,这个时候对外提供
的服务也需要拆分成多个,同时需要客户端配合你进行改造
所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这甲实现,诸如认证、鉴权、监控、路由转发等等
添加上AP网关之后,系统的架构图变成了如下所示:
网关作为流量的入口,常用的功能包括路由转发,权限校验,限流等。
Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,定位于取代Netflix Zuul1.O。相比Zuul来说,Spring Cloud Gateway提供更优秀的性能,更强大的有功能
Spring Cloud Gateway是由WebFlux+Ney+Reactor实现的响应式的API网关。它不能在传统的servlet容器中工作,也不能构建成war包,
Spring Cloud Gateway旨在为微服务架构提供一种简单且有效的API路由的管理方式,并基于Filter方式提供网关的基本功能,例如说安全认证、监控、限流等等
1、基于Spring Framework5,Project Reactor和Spring Boot2.0进行构建;
2、动态路由:能够匹配任何请求属性:
3、支持路径重写;
4、集成Spring Cloud服务发现功能(Nacos、Eruka);
5、可集成流控降级功能(Sentinel、.Hystrix);
6、可以对路由指定易于编写的Predicate(断言)和Filter(过滤器);## gateway是如何实现转发
父pom中使用的依赖:
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.8.RELEASE</spring-cloud-alibaba.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- springcloud的版本依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
gateway模块使用的依赖
<dependencies>
<!-- gateway依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
gateway的application.yml配置信息
server:
port: 8088
spring:
main:
web-application-type: reactive
application:
name: gateway
# gateway的配置
cloud:
gateway:
#路由规则
routes: #路由,数组[这里可以放置多个路由]
#评分管理模块网关路由配置
- id: shop_router #当前路由标识-要求唯一,默认是UUID;
uri: http://localhost:8089 #请求最终要被转发的地址;
order: 1 #路由的优先级——数字越小,代表路由的优先级越高
predicates: #断言:(条件判断——转发请求要满足的条件)
# - Path=/shop/** #当请求路径满族path指定的规则时,此路由信息才会正常转发;
# filters: #过滤器,是在请求传递过程中对请求做一些手脚;
# - StripPrefix=1 #在请求转发之前去掉一层路径
- Path=/TestController/**
- After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]
- CheckAuth=gys
Spring Cloud Gateway(简称Gateway)支持断言Predicate功能,该断言功能是基于Spring WebFlux的HandlerMapping实现的。Gateway包含了很多路由断言工厂,并且这些工厂对应着HTTP请求的很多属性进行了处理,当客户端HTTP请求时,HandlerMapping会获取请求参数,并与Gateway中配置的Predicates进行比对,若满足规则就按规则约定进行路由放行,否则拒绝访问或报404错误。
官网地址
在配置文件中断言标签下配置的Path,After,都是内置断言,也就是gateway自己给提供的断言
例如:
基于Datatime类型的断言工厂
此类型的断言根据时间做判断,主要有三个:
AfterRoutePredicateFactory:接收一个日期参数,判断请求日期是否晚于指定日期
BeforeRoutePredicateFactory:接收一个日期参数,判断请求日期是否早于指定日期
BetweenRoutePredicateFactory:接收两个日期参数,判断请求日期是否在指定时间段内
自定义路由断言工厂需要继承AbstractRoutePredicateFactory类,重写apply方法的逻辑。在apply方法中可以通过exchange…getRequest()拿到ServerHttpRequest对象,从而可以获取到情求的参数、清求方式、清求头等信息,
注意点:
1、必须spring组件(必须是bean)
2.类必须加上RoutePredicateFactory作为结尾(约定大于配置)
3.必须继承AbstractRoutePredicateFactory
4.必须声明静态内部类(config)声明属性来接收配置文件中对应的断言的信息
通过shoutcutFieldOrder集合去返回输入内容的信息
5.需要结合shortcutFieldOrderi进行绑定
6,通过apply进行逻辑判断tue就是匹配成功false匹配失败
@Component
public class CheckAuthRoutePredicateFactorya extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactorya.Config> {
public CheckAuthRoutePredicateFactorya() {
super(Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("name");
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
if (config.getName().equals("gys")){
return true;
}
return false;
}
};
}
/**
* @description: 用于接收配置文件中断言的信息
* @author:
* @date: 2023/9/19 19:52
* @param:
* @return:
**/
@Validated
public static class Config {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
1、功能不同:断言用于匹配请求的某些条件,例如请求路径、请求头、请求参数等,它决定了请求是否应该被路由到特定的目标服务。而过滤器用于对请求进行处理和转换,例如添加请求头、修改请求体、记录日志、实现认证授权等。
2、工作原理不同:断言通常用于路由选择的阶段,在接收请求时进行匹配,如果匹配成功,则将请求路由到相应的目标服务。而过滤器则是在请求路由之前或之后应用的,用于对请求进行预处理或后处理,它不会影响路由的选择。
3、使用场景不同:断言通常用于根据请求的某些属性进行路由选择,因此它更贴近网关的底层实现。而过滤器则更加灵活,可用于实现业务逻辑,例如认证授权、请求重试、流量控制等。