SpringCloud Gateway 简介
为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而 WebFlux 框架底层则使用了高性能的Reactor模式通信框架Netty. SpringCloud GateWay 提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
特征
- 基于 Spring Framework 5 + Spring Boot 2.0 构建
- 基于 Spring Webflux,Project Reactor 和 Netty
- 动态路由, 能够匹配任何请求属性上的路由
- 支持内置到 Spring Handler 映射中的路由匹配
- 支持基于 HTTP 请求的路由匹配(Path、Method、Header、Host 等等)
- Predicates 和 Filters 作用于特定路由
- 集成 Hystrix 断路器
- 集成 Spring Cloud DiscoveryClient,与服务发现与注册配合使用
- 过滤器可以修改 HTTP 请求和 HTTP 响应(增加/修改 Header、增加/修改请求参数、改写请求 Path 等等)
- 易于编写的 Predicates 和 Filters
- 限流
- 路径重写
简单说明一下上文中的三个术语:
(1)Filter(过滤器):
和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。
(2)Route(路由):
网关配置的基本组成模块,一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。
(3)Predicate(断言):
这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。
架构
Spring 在2017年下半年迎来了Webflux,Webflux的出现填补了Spring在响应式编程上的空白,Webflux的响应式编程不仅仅是编程风格的改变,而且对于一系列的著名框架,都提供了响应式访问的开发包,比如Netty、Redis等等。
旧的servlet io 模型
servlet 由 servlet container进行生命周期管理。container启动时构造servlet对象并调用servlet init()进行初始化;container关闭时调用servlet destory()销毁servlet;container运行时接受请求,并为每个请求分配一个线程(一般从线程池中获取空闲线程)然后调用service()。
这种线程模型的弊端:
一个请求进入 servlet 容器时,就会为请求绑定一个线程,一旦并发上升,线程数急剧增加,请求的处理速度降低。系统负载急剧上升。我们其实是不需要为每一个请求开启一个线程的,这种线程模型在系统高并发下没有优势可言。
SpringCloud GateWay io 模型
Webflux模式替换了旧的Servlet线程模型。用少量的线程处理request和response io操作,这些线程称为Loop线程,而业务交给响应式编程框架处理,响应式编程是非常灵活的,用户可以将业务中阻塞的操作提交到响应式框架的work线程中执行,而不阻塞的操作依然可以在Loop线程中进行处理,大大提高了Loop线程的利用率。
工作流程
- 客户端向Spring Cloud Gateway发出请求。然后在GateWay Handler Mapping中找到与请求相匹配的路由,将其发送到GateWay Web Handler。
- Handler再通过制定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。 过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(”pre”)或之后(”post”)执行业务逻辑。
- Filter在‘pre’类型的过滤器可以做参数校验、流浪监控、日志输出、协议转换等, 在’post‘类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。
- 请求通过鉴权校验后,最后会在NettyRoutingFilter 使用 NettyHttpClient 发起请求到特定的微服务机器。
根据服务名由配置
官网链接:链接
配置 spring.cloud.gateway.discovery.locator.enabled = true 即可根据eureka注册的服务名路由
(Configuring Predicates and Filters For [DiscoveryClient](https://cloud.spring.io/spring-cloud-gateway/reference/html/#configuring-predicates-and-filters-for-discoveryclient-routes)
Routes)
By default, the gateway defines a single predicate and filter for routes created with a DiscoveryClient.
The default predicate is a path predicate defined with the pattern /serviceId/**, where serviceId is the ID of the service from the DiscoveryClient.
The default filter is a rewrite path filter with the regex /serviceId/(?.*) and the replacement /${remaining}. This strips the service ID from the path before the request is sent downstream.
If you want to customize the predicates or filters used by the DiscoveryClient routes, set spring.cloud.gateway.discovery.locator.predicates[x] and spring.cloud.gateway.discovery.locator.filters[y]. When doing so, you need to make sure to include the default predicate and filter shown earlier, if you want to retain that functionality. The following example shows what this looks like:
Example 65. application.properties
spring.cloud.gateway.discovery.locator.predicates[0].name: Path
spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'"
spring.cloud.gateway.discovery.locator.predicates[1].name: Host
spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'"
spring.cloud.gateway.discovery.locator.filters[0].name: CircuitBreaker
spring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceId
spring.cloud.gateway.discovery.locator.filters[1].name: RewritePath
spring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/(?.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"