Gateway新一代网关
zuul路由网关
zuul核心人员走了两个,zuul2的研发过久,spring公司等不及,自己研发的Gateway网关。
简介
Cloud全家桶有个狠重要的组件就是网关,在1.x版本中都是采用Zuul网关;但是在2.x版本中,zuul的升级一致跳票,SpringCloud最后自己研发了一个网关替代Zuul, 那就是SpringCloud Gateway
-
Gateway是在Spring生态之上构建的API网关服务,基于Spring 5,Spring Boot 2和Project Reactor 等技术。
-
Gateway旨在提供一种简单而有效 等方式来对API 进行路由,以及提供一些强大对过滤器,例如:熔断、限流、重试等
-
Gateway 作为SpringCloud 等目标提供统一等路由方式且基于Filter 链的方式提供了网关基本的功能,例如:安全,监控。限流
-
SpringCloud Gateway 使用的Webflux中的 reactor-netty 响应式的编程,底层使用了Netty通讯框架
![在这里插入图片描述](img-blog.csdnimg.cn/![202008300…](img-blog.csdnimg.cn/20200830093…)
因为Zuul1.0 进入了维护阶段,而且Gateway 是SpringCloud 团队开发,比Zuul更加的便捷
Gateway 是基于异步非阻塞模型上进行开发的,性能方面不需要担心
SpringCloud Gateway 与 Zuul 的区别
三大核心概念
Route (路由)
- 路由是构建网关的基本模块,它由ID,目标URL,一系列的断言和过滤器组成,如果断言为true则匹配该路由
Predicate (断言)
- 参考的是Java8的java.util.function.predicate
- 开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
Filter (过滤)
- 指的是Spring框架中的GatewayFilter 的实例,使用过滤器,可以在请求被路由前或者之后请求进行修改。
总体
- web请求,通过一些匹配条件,定位到真正的服务节点。并在这个妆发过程的前后,进行一些精细化控制。
- predicate就是我们匹配条件;而filter ,就可以理解为一个无所不能的拦截器,有了这两个元素,在加上目标uri,就可以实现一个具体的路由了
Gateway工作流程
(官网总结)
Demo
- 新建模块cloud-gateway-gateway9527
- 引入pom
<dependencies>
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.angenin.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
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/
- 主启动类
@SpringBootApplication
@EnableEurekaClient
public class GatewayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GatewayMain9527.class, args);
}
}
- 启动微服务 Eureka server 7001 client 8001 + Gateway 9527
通过我们 9527 网关访问 8001的接口
这里起到了作用
Gateway网关路由的两种配置方式
-
在配置文件中配置 在配置文件yml中配置
-
在配置类中配置 代码中注入RouteLocator的Bean
案例(访问百度)
新建config.GatewayConfig
package com.yxl.cloud.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route_angenin", //id
r -> r.path("/guonei") //访问 http://localhost:9527/guonei
.uri("http://news.baidu.com/guonei")); //就会转发到 http://news.baidu.com/guonei
routes.route("path_route_angenin2", //id
r -> r.path("/guoji") //访问 http://localhost:9527/guoji
.uri("http://news.baidu.com/guoji")); //就会转发到 http://news.baidu.com/guonji
return routes.build();
}
}
访问:http://localhost:9527/guonei
通过微服务名实现动态路由
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名称进行路由(默认false)
routes:
- id: payment_route #路由的id,没有规定规则但要求唯一,建议配合服务名
# uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-provider-hystrix-payment
predicates:
- Path=/payment/get/** #断言,路径相匹配的进行路由
- id: payment_route2
# uri: http://localhost:8001
uri: lb://cloud-provider-hystrix-payment
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/
Predicate的使用
官网:cloud.spring.io/spring-clou…
SpringCloud Gateway 将路由匹配作为Spring WebFlux HandlerMapping 基础架构的一部分。
SpringCloud Gateway 包括许多内置的Route Predicate工厂。所有这些Predicate 都与HTTP请求的不同属性匹配。多个Route Predicate工厂可以进行组合
SpringCloud Gateway 创建Route 对象时,使用RoutePredicateFactory 创建 Predicate,Predicate 对象可以赋值给Route。Springcloud Gateway 包含许多内置的 Route Predicate Factories.
所有这些动词 都匹配HTTP请求的不同属性,多种谓词工厂可以组合,通过逻辑and
简单使用
public class T2 {
public static void main(String[] args) {
//获取当前时间串
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);
//2020-06-17T11:53:40.325+08:00[Asia/Shanghai]
}
}
#指定时间前才能访问(Before)
- Before=2020-06-17T11:53:40.325+08:00[Asia/Shanghai]
#指定时间内才能访问(Between)
- Between=2020-06-17T11:53:40.325+08:00[Asia/Shanghai],2020-06-17T12:53:40.325+08:00[Asia/Shanghai]
Cookie
yml 设置 cookie
- Cookie=username,angenin #带Cookie,并且username的值为angenin
不带cookie 直接访问失败
Header
# - After=2020-06-17T12:53:40.325+08:00[Asia/Shanghai]
# - Cookie=username,angenin #带Cookie,username的值为angenin
- Header=X-Request-Id, \d+ #请求头要有 X-Request-Id属性并且值为整数的正则表达式
Method
- Method=GET #只允许get请求访问
总结
Filter的使用
路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。
SpringCloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生
GatewayFilter(31种) Global Filter(10种)
package com.yxl.cloud.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Date;
@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 uname = exchange.getRequest().getQueryParams().getFirst("uname");
if(uname ==null){
log.info("*******用户名为null,非法用户!!");
//设置响应,不被接受
exchange.getResponse().setStatusCode(HttpStatus.NO_CONTENT);
return exchange.getResponse().setComplete();
}
//返回chain.filter(exchange),放行
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
http://localhost:9527/payment/lb?xxx=111
- 个人博客: blog.yanxiaolong.cn/