1. 什么是API网关
API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。
API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。
API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。
API网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:
客户端请求多个微服务,各个服务ip不一样,增加客户端复杂度。
存在跨域,在一定场景下处理相对复杂。
认证复杂,每个服务都需要独立认证。
与微服务耦合太强,微服务变更,客户端需要变更
2. 使用API网关的好处
所有的外部请求都会先经过API 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 API 网关来做,这样既提高业务灵活性又不缺安全性。
- 易于监控
- 统一认证
- 减少客户端与微服务交互,解耦接口依赖
3. 常用网关
Nginx+lua
Zuul Zuul是一种提供动态路由、监视、弹性、安全性等功能的边缘服务。Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器
SpringCoud Gateway Spring Cloud GateWay是Spring Cloud的⼀个全新项⽬【SpringCloud公司开发的】,⽬标是取代Netflix Zuul。
它基于Spring5.0+SpringBoot2.0+WebFlux(基于⾼性能的Reactor模式响应式通信框架Netty,异步⾮阻塞模型)等技术开发,性能⾼于Zuul。
官⽅测试,GateWay是Zuul的1.6倍,旨在为微服务架构提供⼀种简单有效的统⼀的API路由管理⽅式。
4. gateWay入门使用
4.-1 基本概念
- 路由:路由是构建网关的基本模块,它由ID,目标URI,一系列的断言Predicates和过滤器Filters组成,如果断言为true,则匹配该路由。
- 断言:参考Java8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容,例如请求头或请求参数,如果请求与断言相匹配则进行路由。
- 过滤:Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或后对请求进行修改。基于过滤器可以实现:安全,监控,限流等问题。
4.0 创建一个服务
ip配置为80端口,当访问这个服务,就是访问我们的getWay。
# 服务端口
server.port=80
# 服务名
spring.application.name=service-gateway
4.1 请求转发的实现
导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
添加配置文件
server:
port: 9527
spring:
application:
name: springcloud-gateway
cloud:
gateway:
routes: # routes 是路由,一个GateWay可以包含多个route
- id: to-user # 路由的id,必须唯一
uri: http://localhost:8002 # 路由地址,表示目标跳转目的路径
predicates: # predicates 是断言,一个gateWay可以包含多个predicate
- Path=/*/user/** # 断言规则,表示代理什么路径
# 上述表示: 当访问 http://localhost:9527/XX/user/XX/XX 时 会真正访问 http://localhost:8002/XX/user/XX/XX
---
spring:
application:
name: springcloud-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848 # 当有了注册中心时,网关也是一个服务,所以需要注册到注册中心去。
gateway:
discovery:
locator:
enabled: true # 让gateway从nacos中获取服务信息
routes: # routes 是路由,一个GateWay可以包含多个route
- id: to-user # 路由的id,必须唯一
uri: lb://springcloud-consumer # lb 动态路由。 因为有了注册中心,uri可以不像上面那样写死了。所以这里 *****后面跟要调用的服务名称,而不再是具体哪个地址******,因为你可能用了rabbon做负载均衡,会有多个不同的端口。但是你的服务名肯定是一样的
predicates: # predicates 是断言,一个ateWay可以包含多个predicate
- Path=/*/user/** # 断言规则,表示代理什么路径
# 动态路由 GateWay支持动态路由。
路由断言工厂:Spring Cloud Gateway包括许多内置的路由断言工厂。所有这些断言都与HTTP请求的不同属性匹配。您可以将多个路由断言工厂与逻辑 and 语句结合使用。
4.2 跨域问题的解决
在4.1 getWay服务下,创建全局配置类:
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedMethod("*");
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
5. Gateway内置网关(局部)过滤器
Gateway分为Pre类型的过滤器和Post类型的过滤器。
- Pre类型的过滤器在请求转发到后端微服务之前执行,在Pre类型过滤器链中可以做鉴权、限流等操作。
- Post类型的过滤器在请求执行完成之后、将结果返回给客户端之前执行。
在Spring Cloud Gateway中内置了很多Filter,自定义Filter有两种实现,分别是GatewayFilter和GlobalFilter。
GlobalFilter全局过滤器会应用到所有的路由上。
GatewayFilter网关过滤器只会应用到单个路由或者一个分组的路由上。
5.1 Path路径过滤器(常用)
Path过滤器可以实现URL重写,通过重写URL可以实现隐藏真实路径提高安全性。
5.1.1 RewritePath网关过滤器
RewritePath网关过滤器工厂采用路径正则表达式参数和替换参数,使用Java正则表达式来灵活地重写请求路径。
6. Gateway内置网关(全局)过滤器
前言:全局过滤器加上网关过滤器组成过滤器链,该过滤器链的执行顺序是根据@Order注解指定的数字大小,从小到大进行排序,数字越小,优先级越高。
# 对输出响应头设置属性
spring:
cloud:
gateway:
# 配置全局默认过滤器
default-filters:
# 往响应过滤器中加入信息
- AddResponseHeader=token,48945165
7. Gateway自定义网关(局部)过滤器GatewayFilter
自定义(局部)网关过滤器:https://www.bilibili.com/video/BV1R7411774f?p=42&spm_id_from=pageDriver
因为Gateway提供了很多Gateway内置网关(局部)过滤器,所以一般很少使用Gateway自定义网关过滤器。
8. Gateway自定义网关(全局)全局过滤器GlobalFilter
常见需求:用户需要登录了才放行。
自定义类实现 GlobalFilter , Ordered 接口,加上@Component注解即可;
@Component
public class MyCustomerGlobalFilter implements GlobalFilter ,Ordered {
// 参数1:
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChainchain) {
System.out.println("自定义全局过滤器"); // 在这里面做逻辑处理,判断token,并验证账号密码
return chain.filter(exchange);
}
// 该方法用于声明该过滤器执行的优先级
@Override
public int getOrder() { // 返回值越低,表示过滤器执行的优先级越高。
return -2;
}
}