1. 简述
1.1 网关
单体应用拆分成多个服务后,对外需要一个统一入口,解耦客户端与内部服务。
网关核心功能是路由转发,因此不要有耗时操作在网关上处理,让请求快速转发到后端服务上。网关还能做统一的熔断、限流、认证、日志监控等。
可以和服务注册中心完美的整合,如:Eureka、Consul、Nacos
1.2 Spring Cloud Gateway
在 SpringCloud 微服务体系中,有个很重要的组件就是网关,在 1.x 版本中都是采用的 Zuul 网关;但在 2.x 版本中,Zuul 的升级一直跳票,SpringCloud 最后自己研发了一个网关替代 Zuul,那就是 SpringCloud Gateway。
网上很多地方都说 Zuul 是阻塞的,Gateway 是非阻塞的,这么说是不严谨的,准确的讲 Zuul1.x 是阻塞的,而在 2.x 的版本中,Zuul 也是基于 Netty,也是非阻塞的,如果一定要说性能,其实这个真没多大差距。
SpringCloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。而为了提升网关的性能,SpringCloud Gateway 是基于 WebFlux 框架实现的,而 WebFlux 框架底层则使用了高性能的 Reactor 模式通信框架 Netty。
1.3 Gateway 功能特征
- 基于 Spring Framework 5、Project Reactor 和 Spring Boot 2.0 进行构建;
- 动态路由:能够匹配任何请求属性;
- 集成 Spring Cloud 服务发现功能;
- 可以对路由指定 Predicate(断言)和 Filter(过滤器);
- 易于编写的 Predicate(断言)和 Filter(过滤器);
- 集成Hystrix的断路器功能;
- 请求限流功能;
- 支持路径重写。
上图中是核心的流程图,最主要的就是 Route、Predicates 和 Filters 作用于特定路由。
- Route:路由是网关的基本构件。它由 ID、目标 URI、谓词集合和过滤器集合定义;如果聚合谓词为真,则匹配路由;
- Predicate:参照 Java8 的新特性 Predicate。这允许开发人员匹配 HTTP 请求中的任何内容,比如头或参数;
- Filter:指的是框架中 GatewayFilter 的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
1.4 工作原理
客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。
- Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等;
- 在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用;
- 核心逻辑就是路由转发,执行过滤器链。
2. 案例
- 新建模块:cloud-gateway-gateway-9527
- 新增依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
- 新建 application.yml(通过微服务名实现动态路由)
server: port: 9527 spring: application: name: cloud-gateway cloud: gateway: routes: - id: cloud-payment-service # 路由ID,没有固定规则但要求唯一,建议配合服务名 uri: http://localhost:8001 # 匹配后提供服务的路由地址 predicates: # 断言, 路径相匹配的进行路由 - Path=/payment/** eureka: instance: hostname: cloud-gateway-service client: service-url: register-with-eureka: true fetch-registry: true defaultZone: http://eureka7001.com:7001/eureka
- 除了在配置文件中配置外,还可以在代码中注入 RouteLocator(略
- 访问
http://localhost:9527/payment/lb
,可以在浏览器中看到 Payment8001 响应的服务端口
3. 动态路由
结合注册中心实现动态路由:
spring:
application:
name: cloud-gateway
cloud:
gateway:
# 默认情况下 Gateway 会根据注册中心的服务列表,以注册中心上
# 微服务名为路径创建动态路由进行转发,从而实现动态路由的功能
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能
lower-case-service-id: true
访问 http://localhost:9527/cloud-payment-service/payment/lb
,还可以看到负载均衡的效果。
3. Predicate 的使用
// TODO
4. Filter 的使用
// TODO