什么是微服务网关
在微服务众多的服务的治理过程中,服务网关的作用在微服务框架中可以提供统一入口
、鉴权校验
、动态路由
、降低耦合度
的功能,关于springcloud的网关有三个,分别是zuul、zuul2和gateway,其中zuul/zuul2是Netflix公司开发的,但是因为zuul的性能不够好,zuul2的开发内部有歧义,所以springcloud便自研了一套网关——gateway。
组件名称 | 所属公司 | 组件简介 |
---|---|---|
zuul | Netflix | 停更进维 |
zuul2 | Netflix | 由于zuul核心开发人员离职了3人,神仙打架,出路不明 |
gateway | springcloud | springcloud自研的一套非阻塞的网络异步网关 |
关于Gateway
Gateway
是在Spring
生态系统之上构建的API网关服务,基于Spring 5
,,Spring Boot 2
和Project Reactor
等技术。Gateway旨在提供-种简单而有效的方式来对API进行路由, 以及提供一些强大的过滤器功能, 例如: 熔断、限流、重试等。
SpringCloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x
非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux
框架实现的,而WebFlux
框架底层则使用了高性能的Reactor
模式通信框架Netty
。
Spring Cloud Gateway的目标提供统-的路由方式且基于 Filter链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。Spring Cloud Gateway的目标提供统-的路由方式且基于 Filter链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
zuul 和 gateway
基本对比
zuul | zuul2 | Gateway | |
---|---|---|---|
所属公司 | Netflix | Netflix | springcloud |
springboot版本 | springcloud 1.x | Springcloud 2.x | Springcloud 2.x |
架构 | 基于Servlet 2.5,使用阻塞架构,不支持任何长连接 | 基于Netty非阻塞 | 基于webFlux非阻塞 |
长连接 | 不支持任何长连接 | 支持 | 支持 |
性能 | 已过时 | 较好 | 较好 |
webflux
webflux
是一个非阻塞的web框架,类似springmvc
。传统的Web框架,比如说: struts2
, springmvc
等都是基于Servlet API
与Servlet
容器基础之上运行的。但是在Senv/let3.1之后有了导步非阻塞的支持。而WebFlux是-个典型非阻塞异步的框架,它的核心是基于Reactor
的相关API实现的。相对于传统的web框架来说,它可以运行在诸如Netty
,Undertow
及支持Servlet3.1
的容器 上。非阻塞式+函数式编程(Spring5必须让你使用java8)Spring WebFlux是Spring 5.0引入的新的响应式框架,区别于Spring MVC
, 它不需要依赖Servlet API, 它是完全异步非阻塞
的,并且基于Reactor
来实现响应式流规范。
gateway原理
三要素
-
Route
(路由)路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由
-
Predicate
(断言)判断请求的转发条件
-
Filter
(过滤)指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
工作原理
客户端向Spring Cloud Gateway发出请求,然后在
Gateway Handler Mapping
中找到与请求相匹配的路由,将其发送到Gateway web hander
Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前( "pre" )或之后( "post" )执行业务逻辑。
Filter在"pre” 类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在"post"类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。
搭建gateway
注意事项
- gateway 需要注册到注册中心,这里我使用的是
Eureka
,其他注册中心也可。 - gateway项目不能同时依赖
spring-boot-starter-web
依赖
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
配置路由
其中:
yml 方式示例
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}
上面这个配置的意思是,访问gateway-host/red/xxx
或者gateway-host/blue/xxx
的话,这个请求会转发到https://example.org
,相当于https://example.org/red/xxx
或https://example.org/blue/xxx
,实现了一个转发
的功能。我们还可以用硬编码的方式来实现上面的配置。
注入RouteLocator的方式示例
@Configuration
public class GatewayConfiguration {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("host_route",r->r.path("/red/{segment},/blue/{segment}").uri("https://example.org")).build();
return routes.build();
}
}
这样的方式就需要注入routeLocator来实现网关服务的配置。两种方式的效果都一样的,个人建议使用yml配置的方式。
通过微服务名动态路由
修改配置
spring:
application:
name: cloud-springcloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能
routes:
- id: userinfo_user
uri: lb://cloud-eureka-provide-userinfo-service # lb协议表示启用负载均衡功能,然后后面跟着微服务名称
predicates:
- Path=/user/**
过滤器
自定义过滤器
@Component
public class CustomFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
/**
* 从请求中获取是否有token参数
*/
String token = exchange.getRequest().getQueryParams().getFirst("token");
if (token==null){
/**
* 直接拒绝
*/
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
/**
* 通过这个过滤器,进入过滤链中的下一个过滤器
*/
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
总结
springcloud的gateway还是非常强大的,这边笔记只能说做了简单的了解,要发掘其强大的功能依然建议查阅 官网
在我学习过程中觉得美中不足的地方就是这些服务只能通过配置的方式来加入,而不能像添加到数据库中这么方便,是否每次有服务变动了就需要更改网关(配置)呢?后面会学习到springcloud的配置中心,应该可以解决这个问题。不过用起来和我之前用到的kong
网关还是各有优劣吧。