08 服务网关GateWay
GateWay 网关
Cloud 组件全家桶中有一个重要的组件就是网关,在1.x 版本都是采用的 Zuul网关;
但在 2.x 版本中,zuul 的升级一直跳票,SpringCloud 最后自己研发了一个网关替代Zuul.
GateWay 为了提供一种简单而有效的方式来对 API 进行路由 以及提供一些强大的过滤器功能,例如:熔断、限流、重试等
选择 GateWay 的原因
Zuul 1 的模型
三大概念
Route(路由):构建网关的基本模块,它由ID,目标URI,一系列的断言
和过滤器组成,如果断言为true则匹配该路由
Predicate(断言):开发人员可以匹配 HTTP 请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
Filter(过滤):是SpringCloud框架中的 GateWay的实例,使用过滤器,可以在请求被路由前或者路由之后对请求进行修改
搭建 网关9527
- 新建模块cloud-gateway-gateway9527
- pom
网关的pom 文件不需要 web 和 auactor 依赖
<dependencies>
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!--eureka client(通过微服务名实现动态路由)-->
<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>
- yml
server:
port: 9527
spring:
application:
name: cloud-gateway
eureka:
instance:
hostname: cloud-gateway-service
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
- 主启动类
@SpringBootApplication
@EnableEurekaClient
public class GatewayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GatewayMain9527.class,args);
}
}
- 修改yml文件
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
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:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
- 测试 启动 7001 网关9527 8001
通过9527 访问到 8001
predicate 为 true 访问成功 false 访问失败
配置路由的两种方式
- 在配置文件yml中配置
- 在配置类中配置
代码中注入RouteLocator的Bean
配置类配置
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route",
r -> r.path("/guonei") // 相当于 localhost:9527/guonei 转到下面的百度
.uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
}
测试:http://localhost:9527/guonei
动态路由
- 修改yml 文件
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名称进行路由(默认false)
routes:
- id: payment_routh #路由的id,没有规定规则但要求唯一,建议配合服务名
# uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://CLOUD-PAYMENT-SERVICE
predicates:
- Path=/payment/get/** #断言,路径相匹配的进行路由
- id: payment_routh2
# uri: http://localhost:8001
uri: lb://CLOUD-PAYMENT-SERVICE
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
测试,启动7001,8001,8002,9527
http://localhost:9527/payment/lb
常用Predicate的使用
After/Before/Between
先用一个测试类获取当前时间
import java.time.ZonedDateTime;
public class Test2 {
public static void main(String[] args) {
//获取当前时间串
ZonedDateTime now = ZonedDateTime.now();//默认时区
System.out.println(now);
//2021-12-04T14:32:44.032+08:00[Asia/Shanghai] }
}
}

在yml 文件 中加上
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
# 时间比当前时间晚了一小时
- After=2021-12-04T15:32:44.032+08:00[Asia/Shanghai]
测试,启动7001,8001,8002,9527
http://localhost:9527/payment/lb
#指定时间前才能访问(Before)
- Before=2021-12-04T15:32:44.032+08:00[Asia/Shanghai]
#指定时间内才能访问(Between)
- Between=2021-12-04T15:32:44.032+08:00[Asia/Shanghai],2021-12-04T16:32:44.032+08:00[Asia/Shanghai]
Cookie Route Predicate
需要两个参数,一个是 Cookie name,一个是正则表达式
路由规则会通过获取对应的Cookie name 值 和 正则表达式,如果匹配上就会执行路由,如果没有匹配上则不执行
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
- After=2021-12-04T15:32:44.032+08:00[Asia/Shanghai]
- Cookie=username,ssyy
Header Route Predicate Factroy
两个参数 一个是属性名称和一个正则表达式,这个属性值和正则表达式匹配执行
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
# - After=2021-12-04T15:32:44.032+08:00[Asia/Shanghai]
# - Cookie=username,ssyy
- Header=X-Request-Id, \d+ #请求头要有 X-Request-Id属性并且值为整数的正则表达式
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
# - After=2021-12-04T15:32:44.032+08:00[Asia/Shanghai]
# - Cookie=username,ssyy
- Header=X-Request-Id, \d+ #请求头要有 X-Request-Id属性并且值为整数的正则表达式
- Host=**.angenin.com #Host: xxx.angenin.com 请求是Host必须有**.angenin.com
- Method=GET #只允许get请求访问
- Path=/payment/lb/** #访问的url地址有 /payment/lb/ 才能访问
- Query=username, \d+ #url请求地址必须带上username参数,并且值必须为整数
Filter
路由过滤器可用于修改进入的 HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用
内置了 许多过滤器 都由 GateWayFilter的工厂产生
GatewayFilter(31种)
Global Filter(10种)
自定义过滤器
新建filter.MyLogGateWayFilter
@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 name = exchange.getRequest().getQueryParams().getFirst("name");
if (name == null){
log.info("********用户名为null,非法用户,T T");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
//返回值是过滤器的优先级,越小优先级越高(最小-2147483648,最大2147483648)
return 0;
}
}
启动7001,8001,8002,9527
http://localhost:9527/payment/lb?name=111
带着 name 就会成功
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)