文章目录
一、gateway是什么?
gateway组件是继zuul之后的又一大网关组件,不过zuul其本身还是基于servlet实现的,换言之还是同步阻塞方式的实现。就其本身来讲它的最根本弊端也是再此。而非阻塞带来的好处不言而喻,高效利用线程资源进而提高吞吐量,基于此Spring率先拿出针对于web的杀手锏,对,就是webflux。而Gateway本身就是基于webflux基础之上实现的。
Spring Cloud Gateway功能:
1.建立在Spring Framework 5,Project Reactor和Spring Boot 2.0之上
2.能够匹配任何请求属性上的路由。
3.谓词和过滤器特定于路由。
4.断路器集成。
5.Spring Cloud DiscoveryClient集成
6.易于编写的谓词和过滤器
7.请求速率限制
8.路径改写
在gateway当中有三个重要的元素他们分别是:
Route :是最核心的路由元素,它定义了ID,目标URI ,predicates的集合与filter的集合,如果Predicate聚合返回真,则匹配该路由
Predicate :基于java8的函数接口Predicate,其输入参数类型ServerWebExchange,其作用就是允许开发人员根据当前的http请求进行规则的匹配,比如说http请求头,请求时间等,匹配的结果将决定执行哪种路由
Filter:GatewayFilter,它是由特殊的工厂构建,通过Filter可以在下层请求路由前后改变http请求与响应
二、工作原理
客户端向Spring Cloud Gateway发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。该处理程序通过特定于请求的过滤器链运行请求。筛选器由虚线分隔的原因是,筛选器可以在发送代理请求之前和之后运行逻辑。所有“前置”过滤器逻辑均被执行。然后发出代理请求。发出代理请求后,将运行“后”过滤器逻辑。
简而言之:客户端发起请求->由Predicate里面所定义的规则选去合适的路由->网关处理程序执行Filter(前置)->转发请求并执行过滤器(后置)
三、入门使用
1.pom引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
2.配置文件
application.yml
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: route1
uri: http://localhost:8001
predicates:
- Path=/payment/**
- id: route2
uri: http://localhost:80
predicates:
- Path=/order/**
eureka:
client:
service-url:
defaultZone: http://eurekaserver7001.com:7001/eureka/
上述路由配置中,访问路径是/payment开头那么路由到8001端口,访问路径是/order开头那么路由到80端口。
3.启动类
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GatewayMain9527.class);
}
}
4.测试
为了测试gateway功能,还需要启动注册中兴Eureka,启动两个微服务(payment,consumer)这个两个微服务中只写一个方法就是返回当前服务的端口。
eureka截图
访问路径 http://localhost:9527/payment/getPort
访问路径 http://localhost:9527/order/getPort
测试通过。
四、Route(路由)
在上述入门操作步骤中,路由配置为指定的微服务的地址,但是在实际使用场景中,我们搭建的是微服务的集群,所以此时只是配置一个指定的路由地址就显得有些相形见绌了。
所以能不能有一种配置方式适用于集群环境下?
答案是可以的,在学习Ribbon+restTemplate和Fegin中我们是使用微服务注册到注册中心的Application.name来作为请求转发的地址,如今gateway也同样注册在Eureka中,那么也可以如此使用。
(官网解释)
1.修改application.yml
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: route1
uri: lb://CLOUD-PAYMENT-SERVICE
predicates:
- Path=/payment/**
- id: route2
uri: lb://CLOUD-CONSUMER-SERVICE
predicates:
- Path=/order/**
eureka:
client:
service-url:
defaultZone: http://eurekaserver7001.com:7001/eureka/
2.测试
重新启动gateway测试
访问路径 http://localhost:9527/payment/getPort
访问路径 http://localhost:9527/order/getPort
测试通过。
五、Predicate(断言)
从工作原理可以知道,Predicate的作用就是确定路由的规则。
官网提供了十一种类型Predicate
The Path Route Predicate Factory:根据访问路径匹配路由(这个是比较常用的Predicate,上一个目录里面的配置就是这个)
官网实例:
spring:
cloud:
gateway:
routes:
- id: path_route
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}
这些Predicate官网都有非常详细的实例,并且可以组合使用,所以此处就不再过多解释,把官网地址贴在此处,如有需要自己查看一下即可,链接: Spring-gateway.
六、Filter(过滤器)
gateway给我们提供的Filter可以分为单一过滤器(GatewayFilter )和全局过滤器( Global Filters)
1、单一过滤器
官网提供的单一过滤器一共有30种之多,这里就不一一展示了,官网的实例非常详细,同样是把链接贴到此处如有需要,自行查看,链接: Spring-gateway.
下面测试一种单一过滤器(The SetPath GatewayFilter Factory)
The SetPath GatewayFilter Factory:修改请求访问路径
修改application.yml
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: route1
uri: lb://cloud-payment-service
predicates:
- Path=/payment/**
- id: route2
uri: lb://cloud-consumer-service
predicates:
- Path=/test/order/**
filters:
- SetPath=/order/getPort
eureka:
client:
service-url:
defaultZone: http://eurekaserver7001.com:7001/eureka/
orderController
@RestController
@Slf4j
@RequestMapping("/order")
public class OrderController {
@Value("${server.port}")
public String port;
@GetMapping("/getPort")
public String getPort(){
return port;
}
}
我们将访问/test/order,测试是否可以将顺利路由到后台的/order所指向的controller中。
测试通过。
2、全局过滤器
在springgateway中配置全局过滤器需要实现两个接口GlobalFilter, Ordered。
下面写一个全局过滤器判断请求头里test字段值是否为123,如果test字段值为123则不做任何处理,不是则返回错误信息
新增GlobalFilterConfig配置类
@Configuration
@Slf4j
public class GlobalFilterConfig {
@Bean
public MyGlobalFilter getMyGlobalFilter(){
return new MyGlobalFilter();
}
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String value = exchange.getRequest().getHeaders().getFirst("test");
if(!value.equals("123")){
log.info("value值为空");
exchange.getResponse().setStatusCode(HttpStatus.BAD_GATEWAY);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
}
测试:
test值为456时,如下图
test值为123时,如下图
测试通过。
七、总结
Spring Cloud Gateway 可以看做是一个 Zuul 1.x 的升级版和代替品,比 Zuul 2 更早的使用 Netty 实现异步 IO,从而实现了一个简单、比 Zuul 1.x 更高效的、与 Spring Cloud 紧密配合的 API 网关。
Spring Cloud Gateway 里明确的区分了 Router 和 Filter,并且一个很大的特点是内置了非常多的开箱即用功能,并且都可以通过 SpringBoot 配置或者手工编码链式调用来使用。
以上是个人见解,如有错误,欢迎指正。