目录
- 什么是API网关
- 为什么需要API网关
- 前言
- 问题列表
- API网关解决了什么问题
- 常见的网关解决方案
- Nginx+Lua
- Spring Cloud Netflix Zuul
- SpringCloud Zuul的IO模型
- 弊端
- Spring Cloud Gateway
- 第二代网关——Gateway
- Gateway的特征
- Spring Cloud Gateway的处理流程
- Spring Cloud Gateway的相关概念
- Route(路由)
- Predicate(断言)
- Filter(过滤器)
- 案例
- 需求
- 搭建Gateway微服务网关
- 1.创建项目
- 2.添加Gateway依赖
- 3.修改配置——基础URI的路由配置方式
- 配置解析
- 网关过滤器
- 为网关添加过滤器
- 1.在上述案例的基础上,创建AuthGlobalFilter并实现GlobalFilter、Ordered接口
- 2.重写方法
- 3.filter方法验证token参数
- 4.添加过滤器定义
- 5.验证
什么是API网关
- API Gateway(API 网关),顾名思义,是出现在系统边界上的一个面向 API 的、串行集中式的强管控服务,这里的边界是企业 IT 系统的边界,可以理解为企业级应用防火墙,主要起到隔离外部访问与内部系统的作用。在微服务概念的流行之前,API 网关就已经诞生了,例如银行、证券等领域常见的前置机系统,它也是解决访问认证、报文转换、访问统计等问题的问题列表。
- API 网关的流行,源于近几年来移动应用与企业间互联需求的兴起。移动应用、企业互联,使得后台服务支持的对象,从以前单一的Web应用,扩展到多种使用场景,且每种使用场景对后台服务的要求都不尽相同。这不仅增加了后台服务的响应量,还增加了后台服务的复杂性。随着微服务架构概念的提出,API网关成为了微服务架构的一个标配组件。
- API 网关是一个服务器,是系统对外的唯一入口。API 网关封装了系统内部架构,为每个客户端提供定制的 API。所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有非业务功能。API 网关并不是微服务场景中必须的组件。
为什么需要API网关
前言
- 不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题
问题列表
- 客户端会多次请求不同的微服务,增加了客户端的复杂性。
- 存在跨域请求,在一定场景下处理相对复杂。
- 认证复杂,每个服务都需要独立认证。
- 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施。
- 某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难。
API网关解决了什么问题
常见的网关解决方案
Nginx+Lua
- Nginx 适合做门户网关,是作为整个全局的网关。
- Gateway 可以实现熔断、重试等功能,这是 Nginx 不具备的。
Spring Cloud Netflix Zuul
- Zuul 是 Netflix 公司开源的一个 API 网关组件,Spring Cloud 对其进行二次基于 Spring Boot 的注解式封装做到开箱即用。
- 可以做到请求转发,根据配置或者默认的路由规则进行路由和 Load Balance,无缝集成 Hystrix。
SpringCloud Zuul的IO模型
- Zuul 是Netflix出品的开源微服务网关,可与 Eureka、Ribbon、Hystrix 等组件配合使用,
- Zuul 的核心是一系列过滤器
- Spring Cloud中所集成的Zuul版本,采用的是Tomcat容器,使用的是传统的Servlet IO处理模型。
弊端
- servlet是一个简单的网络IO模型,当请求进入servlet container时,servlet container就会为其绑定一个线程,在并发不高的场景下这种模型是适用的
- 但是一旦并发上升,线程数量就会上涨,而线程资源代价是昂贵的(上线文切换,内存消耗大)严重影响请求的处理时间。
- 在一些简单的业务场景下,不希望为每个request分配一个线程,只需要1个或几个线程就能应对极大并发的请求,这种业务场景下servlet模型没有优势。
Spring Cloud Gateway
- Spring Cloud官方推出的第二代网关框架,性能显著提升;
第二代网关——Gateway
- SpringCloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
- SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。
- Spring Cloud Gateway 的目标,不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
Gateway的特征
- 基于Spring Framework 5、Project Reactor和Spring Boot 2.0构建
- 能够在任意请求属性上匹配路由
- predicates(谓词) 和 filters(过滤器)是特定于路由的
- 集成了Hystrix断路器
- 集成了Spring Cloud DiscoveryClient
- 易于编写谓词和过滤器
- 请求速率限制
- 路径重写
Spring Cloud Gateway的处理流程
- 客户端向 Spring Cloud Gateway 发出请求。
- 然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。
- Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
- 过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。
Spring Cloud Gateway的相关概念
Route(路由)
- 网关配置的基本组成模块,和Zuul的路由配置模块类似。
- 一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。
- 如果断言为真,则路由匹配,目标URI会被访问。
Predicate(断言)
- 这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,
- 例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。
Filter(过滤器)
- 和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。
- 过滤器为
org.springframework.cloud.gateway.filter.GatewayFilter
类的实例。
案例
需求
- 提供三个微服务EurekaServer、Consumer端、Provider端
- 通过网关转发微服务请求
- 要求访问Gateway网关,然后转发请求到Consumer端,然后继续调取Provider端服务
搭建Gateway微服务网关
1.创建项目
指定artifactId为:demo-gateway
2.添加Gateway依赖
- 还要添加Spring Cloud依赖,此处省略
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3.修改配置——基础URI的路由配置方式
- 指定服务端口、Eureka Server地址等信息
spring:
application:
name: demo-gateway
cloud:
gateway:
routes:
- id: user-consumer-1
uri: lb://demo-user-consumer
predicates:
- Path=/api/user/**
config:
uri: http://localhost:7600
label: dev
profile: dev
eureka:
client:
service-url:
defaultZone: http://192.168.2.220:7776/eureka
配置解析
属性 | 解释 |
---|---|
id | 我们自定义的路由 ID,保持唯一 |
uri | 目标服务地址, lb代表从注册中心获取服务 |
predicates | 路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂逻辑。 |
Path | 转发地址格式 |
filters | 过滤器链 |
StripPrefix | 作用是去掉请求路径的最前面n个部分截取掉,StripPrefix=1就代表截取路径的个数为1,比如前端过来请求http://localhost:8085/user/login,匹配成功后,路由到后端的请求路径就会变成http://localhost:8082/login |
网关过滤器
- 每个服务在处理请求的时候都要判断是否验证token
- 需要验证token是否有效
- 效率低
- 每个请求都需要转发到具体的微服务后再判断,然后将判断的结果回转给网关
- 在网关转发前就行进过滤处理
- 过滤器
为网关添加过滤器
创建网关过滤器
1.在上述案例的基础上,创建AuthGlobalFilter并实现GlobalFilter、Ordered接口
2.重写方法
- filter:过滤器实现
- getOrder():过滤顺序
3.filter方法验证token参数
public class AuthGlobalFilter implements org.springframework.cloud.gateway.filter.GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("token");
if (token == null || token.isEmpty()) {
System.out.println("token为空,不能通过");
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
4.添加过滤器定义
修改启动类,添加方法
@Bean
public AuthGlobalFilter globalFilter() {
return new GlobalFilter();
}
5.验证
- 请求接口
- 分别携带token和不携带token验证请求结果