博客学习参考视频
GateWay 新网关
① 概述简介
1.官网
- 上一代网关 zuul 1.X:https://github.com/Netflix/zuul/wiki
- 当 前 网 关 gateway :https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/
2.是什么
概述:
一句话:
- SpringCloud Getaway 使用的 Webflux 中的 reactor-netty 响应式编程组件,底层使用的 Netty 通讯框架
- 源码框架
3.能干嘛
- 反向代理
- 鉴权
- 浏览控制
- 熔断
- 日志监控
….
4.微服务架构中网关在哪里
5.有了 Zuul 了怎么又出来了 gateway
我们为什么选择 Gatway?
- neflix 不太靠谱, zuul2.0 一直跳票,迟迟不发布
- SpringCloud Gateway 具有如下特性
- SpringCloud Gateway 与 Zuul 的区别
Zuul1.x 模型
GateWay 模型
- WebFlux 是什么
② 三大核心概念
1.Route(路由)
路由的构建网关的基本模块,它由 ID ,目标 URI , 一系列的断言和过滤器组成,如果断言为 true 则匹配该路由
2. Predicate(断言)
参考的是 java8 的 java.util.function.Predicate 开发人员可以匹配 HTTP 请求中的所有内容(例如请求头或请求参数),如果请求域断言相匹配则进行路由。
3. Filter(过滤)
指的是 Spring 框架中 GatewayFilter 的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
4. 总体
③ Gateway 工作流程
1.官网总结
2.核心逻辑
路由转发 执行过滤器链
④ 入门配置
代码语言:javascript复制新建 Module: cloud-gateway-gateway9527
POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>clould</artifactId>
<groupId>com.oy</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-gateway-gateway9527</artifactId>
<dependencies>
<!--新增 gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.oy</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
代码语言:javascript复制YML
server:
port: 9527
spring:
application:
name: cloud-gateway
eureka:
instance:
hostname: cloud-gateway-service
client: #服务提供者provider注册进eureka服务列表中
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
代码语言:javascript复制业务类 (无)
主启动类
@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GateWayMain9527.class, args);
}
}
**9527 网关如何做路由映射那? ? ? **
- cloud-provider-payment8001 看看 controller 的访问地址
- get
- lb
- 我们目前不想暴露 8001 端口,希望在 8001 外面套一层 9527
代码语言:javascript复制YML 新增网关配置
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名称j进行路由
routes:
- id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
#匹配后提供服务的路由地址
uri: http://localhost:8001
predicates:
- Path=/payment/get/** # 断言,路径相匹配的进行路由
- id: payment_route2
uri: http://localhost:8001
predicates: Path=/payment/lb/** #断言,路径相匹配的进行路由
eureka:
instance:
hostname: cloud-gateway-service
client: #服务提供者provider注册进eureka服务列表中
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
测试
- 启动 7001
- 启动 8001: cloud-provider-payment8001
- 启动 8001: cloud-provider-payment8001
访问说明
- 添加网关前: http://localhost:8001/payment/get/1
- 添加网关后: http://localhost:9527/payment/get/1
YML 配置说明
Gateway 网关路由有两种配置方式
- 在配置文件 yml 中配置 (见前面步骤)
- 代码中注入 RouteLocator 的 Bean
官网案例 :
自己写一个: 业 务 需 求 : 通 过 9527 网 关 访 问 到 外 网 的 百 度 新 闻 网 址 http://news.baidu.com/guoji
代码语言:javascript复制/**
* 配置网关
* @Author OY
* @Date 2020/10/18
*/
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_rote_oy", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
@Bean
public RouteLocator customRouteLocator2(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_rote_oy2", r -> r.path("/guoji").uri("http://news.baidu.com/guoji")).build();
return routes.build();
}
}
测试:
⑤ 通过服务名实现动态
默认情况下 Gateway 会根据注册中心的服务列表,以注册中心上微服务名为路径路径创建动态路由创建动态路由进行转发,从而实现动态路由的功能
启动: 一个 eureka7001 两个服务提供者 8001/8002
POM
代码语言:javascript复制YML: uri: lb//cloud-payment-service
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名称j进行路由
routes:
- id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
#匹配后提供服务的路由地址
#uri: http://localhost:8001
uri: lb//cloud-payment-service
predicates:
- Path=/payment/get/** # 断言,路径相匹配的进行路由
- id: payment_route2
#uri: http://localhost:8001
uri: lb//cloud-payment-service
predicates: Path=/payment/lb/** #断言,路径相匹配的进行路由
eureka:
instance:
hostname: cloud-gateway-service
client: #服务提供者provider注册进eureka服务列表中
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
需要注意的是uri 的协议为 lb ,表示启用 Gateway 负载均衡功能。
lb ://serviceName 是 spring cloud gateway 在微服务中自动为我们创建负载均衡 uri。
测试:
http://localhost:9527/payment/lb: 8001/8002 两个端口切换
⑥ Predicate 的使用
1.是什么
启动我们的 gateway9527
2.Route Predicate Factories 是什么?
3.常用的 Route Predicate
After Route Predicate
问题一
:上述这个 After 好懂,这个时间时间串串,有点不能理解。使用以下方式即可解开谜团。
@Test
public void test1(){
ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
System.out.println(zbj); // 2020-10-18T10:35:52.127 08:00[Asia/Shanghai]
ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/Denver"));// 用指定时区获取当前时间
System.out.println(zny); // 2020-10-17T20:38:37.693-06:00[America/Denver]
}
YML
代码语言:javascript复制- After=2020-10-18T10:38:37.692 08:00[Asia/Shanghai]
Before Route Predicate
YML
代码语言:javascript复制- After=2020-10-18T10:38:37.692 08:00[Asia/Shanghai]
- Before=2020-10-18T10:38:37.692 08:00[Asia/Shanghai]
Between Route Predicate
YML
代码语言:javascript复制- Between=2020-10-18T10:38:37.692 08:00[Asia/Shanghai],2020-10-19T10:38:37.692 08:00[Asia/Shanghai]
Cookie Route Predicate
1) 不带 cookies 访问
2) 带上 cookies 访问
加 入 curl 返 回 中 文 乱 码 :https://blog.csdn.net/leedee/article/details/82685636
代码语言:javascript复制curl http://localhost:9527/payment/lb --cookie "username=oy"
3)YML
代码语言:javascript复制- Cookie=username,oy #并且Cookie是username=oy才能访问
Header Route Predicate
YML
代码语言:javascript复制- Header=X-Request-Id, d #请求头中要有X-Request-Id属性并且值为整数的正则表达式
Host Route Predicate
YML
代码语言:javascript复制- Host=**.somehost.org,**.anotherhost.org
Method Route Predicate
YML
代码语言:javascript复制- Method=GET,POST
Path Route Predicate
YML
代码语言:javascript复制- Path=/red/{segment},/blue/{segment}
Query Route Predicate
YML
代码语言:javascript复制- Query=username, d #要有参数名称并且是正整数才能路由
测试: http://localhost:9527/payment/lb?username=1
小总结
All
说白了,Predicate就是为了实现一组匹配规则, 让请求过来找到对应的Route进行处理
⑦ Filter 的使用
1.是什么
2.Spring Cloud Gateway 的 Filter
- 生命周期, Only Two
- Pre : 在业务逻辑之前
- Post: 在业务逻辑之后
- 种类: Only Two
- GatewayFilter: 单一
- GlobalFilter: 全局
3.常用的 GatewayFilter
AddRequestParameter
YML
4.自定义过滤器
自定义全局 GlobalFilter
- 两个主要接口介绍
impiemerts GlobalFilter , Ordered
- 能干嘛
- 全局日志记录
- 统一网关鉴权
- ……
- 案例代码
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("*********come in MyLogGateWayFilter: " new Date());
String username = exchange.getRequest().getQueryParams().getFirst("username");
if(username == null){
log.info("*****用户名为 NUll 非法用户.(┬_┬)");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);// 给人家一个回应
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
测试
启动
- 正确: http://localhost:9527/payment/lb?username=1
- 错误 : http://localhost:9527/payment/lb?usernameaa=1