[poc]
1/搭建项目
1.1/搭建流程
依赖项
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
spring-cloud-gateway 不能用 web, 要用也是用 webflux
去掉以下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
因为 spring cloud gateway 是基于 webflux 的,如果非要 web 支持的话需要导入 spring-boot-starter-webflux 而不是 spring-boot-start-web
参见 gateway 报错 ServerCodecConfigurer
重要 Spring Cloud Gateway 依赖 Spring Boot和 Spring Webflux 提供的 Netty runtime。
它不能在传统的 Servlet 容器中工作或构建为 WAR
1.2/路由
spring:
application:
name: nacos-gateway
cloud:
nacos:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: true # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
routes:
- id: test-rule
uri: lb://nacos-client
order: -1
predicates:
- Path=/api2/**
filters:
- StripPrefix=1
- id:我们自定义的路由 ID,保持唯一
- uri:目标服务地址
- predicates:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
- filters:过滤规则,
上面那段路由配置表示所有已包含 /api2/ 的url都会被路由到 client-manage服务,StripPrefix=1表示路由时会去除/api2/。
测试
- 服务自身调用
☁ scg_project curl http://localhost:8284/hello
hello 8284
☁ scg_project curl http://localhost:8285/hello
hello 8285
- 网关调用
☁ scg_project curl http://localhost:8283/api2/hello
hello 8284
☁ scg_project curl http://localhost:8283/api2/hello
hello 8285
上述配置还可以用代码实现
@Bean
public RouteLocator divRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r.path("/api2/**")
.filters(f -> f.stripPrefix(1))
.uri("lb://nacos-client")
.order(0)
.id("test-bean-rule"))
.build();
}
1.3/动态路由
org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint#save
https://www.cnblogs.com/xmzJava/p/10767365.html
2/概述
2.1/三要素
-
Route 路由:gateway 的基本构建模块。它由ID、目标URI、断言集合和过滤器集合组成。如果聚合断言结果为真,则匹配到该路由。
-
Predicate 断言:这是一个Java 8 Function Predicate。输入类型是 Spring Framework
ServerWebExchange
。这允许开发人员可以匹配来自 HTTP 请求的任何内容,例如Header或参数。 -
Filter 过滤器:这些是使用特定工厂构建的 Spring Framework
GatewayFilter
实例。所以可以在返回请求之前或之后修改请求和响应的内容。
这是路由的三要素 一个成熟的路由最重要的部分就是由这三部分组成
也是SCG的三要素 不管做什么都是围绕这三个或其中的几个.
2.2/路由断言Factories
After / Before / Between / Cookie / Header / Host / Method / Path
自带的有十个, 可以自行拓展
自带路由断言简单点, 路由断言的意思就是判断这个请求是不是属于这条路由.
2.3/过滤器
2.3.1 过滤器示例
过滤器
配置的两种方式
spring:
cloud:
gateway:
routes:
- id: set_status_route
uri: https://example.org
filters:
- name: SetStatus
args:
status: 401
- id: set_statusshortcut_route
uri: https://example.org
filters:
- SetStatus=401 # shortcut 方式
2.3.2 过滤器实现
要实现一个拦截器, 需要实现两个( Ordered 非必要 )接口
GlobalFilter, Ordered
- Ordered的值越小, 优先级越高, 默认
2147483647
(最小) - @Ordered 注解优先
讲到过滤器就不可不提一下责任链这种经典的设计模式
责任链模式中 最重要的两个元素
- 排好序的过滤器链 -> 过滤器链表
- 当前序号 -> 链中的具体哪个过滤器
过滤器链 GatewayFilterChain / DefaultGatewayFilterChain
过滤器 GatewayFilter
-> LoadBalancerClientFilter ("lb")
-> NettyRoutingFilter ("http/https")
参考 StripPrefixGatewayFilterFactory
直接继承了 AbstractGatewayFilterFactory<StripPrefixGatewayFilterFactory.Config>
- StripPrefixGatewayFilterFactory.Config 就是拦截器后面带的参数, 这里就是一个int值, 表示要截取几位
- AbstractGatewayFilterFactory 提供了 apply 方法, 入参就是 config, 返回一个 GatewayFilter 实例
常见的责任链模式还有 Servlet 的 Filter
其实所有的拦截器链都有一个特性: 当前拦截器可以决定是否要调用下一个拦截器 (直接)
2.3.3 过滤器分类
<1>从 实现/作用 上来分
其实实现一个过滤器有两种方式:
- 创建一个继承了 AbstractGatewayFilterFactory 类的 XxxGatewayFilterFactory 类, 然后在XxxGatewayFilterFactory 的 apply 方法中返回一个 GatewayFilter.
- 直接实现 GlobalFilter 接口 重写 filter 方法.
区别就是作用域不同(路由级别/全局级别) .
SCG 最灵活的一点 插件化过滤器
SCG 自带的局部过滤器有 30 种
局部过滤器
SCG 自带的全局过滤器有 10 种
全局过滤器准确地说应该是九种, 第一种只是一个说明.
2.3.4 Default-GatewayFilter
不过 SCG 提供了一种将路由级别的过滤器提升到全局的简单方式
To add a filter and apply it to all routes, you can use
spring.cloud.gateway.default-filters
. This property takes a list of filters. The following listing defines a set of default filters:
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
- PrefixPath=/httpbin
这样这两个过滤器就变成全局级别的了.
还有一点很重要的就是命名
官方文档明确指出 自定义过滤器的名字需要以 GatewayFilterFactory
结尾
2.4/路由定义
定义一个路由大约有四种方式
2.4.1 配置方式
spring.cloud.gateway.route...
最简单直接的一种方式
4.2 服务发现
spring.cloud.gateway.locator...
- ReactiveCompositeDiscoveryClient_[serviceId]
- 从注册中心拉取注册服务列表
2.4.3 自定义来源
实现 RouteDefinitionRepository 接口, 重写 getRouteDefinition 方法
@Override
public Flux <RouteDefinition> getRouteDefinitions(){
log.info("get_route_definition...");
// 自定义来源 - 配置文件/数据库/redis/内存/mq ...
List <Router> routerList = getConfig();
List <RouteDefinition> routeDefinitions = routerList.stream().map(this::transfer).collect(Collectors.toList());
return Flux.fromStream(routeDefinitions.stream());
}
2.4.4 硬编码
@Bean
public RouteLocator divRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r.path("/api3/**")
.filters(f -> f.stripPrefix(1))
.uri("lb://nacos-client")
.order(-100)
.id("test-bean-rule"))
.build();
}
前三种分别对应了 RouteDefinitionLocator 的三种实现, 最后一种是直接生成了一个 RouteLocator 类 ( DSL 风格 )
CompositeRouteLocator 里的 delegates 就有以下两种
org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder$Builder$$Lambda$494/1864630663@29f8134
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator@77a9ac36
- lambda 这种就是硬编码方式生成的
- 其他三种都会以 RouteDefinitionRouteLocator 的方式生效
还有这么多....
image.png先写到这吧, 下次再补.
醒了个大早却赶了晚集, 还没饭吃...
写了点东西有点感觉了赶紧去看 Nacos ~
网友评论