GateWay网关
一、网关概述
网关旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。
在微服务架构中,不同的微服务可以有不同的网络地址,各个微服务之间通过互相调用完成用户请求,客户端可能通过调用N个微服务的接口完成一个用户请求。
存在的问题:
- 客户端多次请求不同的微服务,增加客户端的复杂性。(如果服务提供方变更了请求地址,那客户端也得修改,这样很麻烦。)
- 认证复杂,每个服务都要进行认证
- http请求不同服务次数增加,性能不高
网关就是系统的入口,封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、缓存、负载均衡、流量管控、路由转发等。
在目前的网关解决方案里,有Nginx+ Lua、Netflix Zuul 、Spring Cloud Gateway等等(GateWay比zull好一点)
解决方案:
- 把请求链接都放到API网关中,如果需要修改,那就修改网关就行了。(微服务项目的服务多了去了,一个个改的话,那得猴年马月啊,直接都放到网关里面进行统一的管理,这样就方便很多了)
- 认证一类的操作都放到网关里面
- 请求都是由网关来转发的,所以多个请求是可以复用的。
二、Gateway网关入门案例
步骤:
1.搭建网关模块
2.引入依赖:starter-gateway
<!--引入gateway 网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- eureka-client 这个是为了后面的动态路由准备的-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3.编写启动类
@SpringBootApplication
@EnableEurekaClient//这个是为了后面的动态路由准备的
public class AppGateway {
public static void main(String[] args) {
SpringApplication.run(AppGateway.class, args);
}
}
4.编写配置文件
server:
port: 80
spring:
application:
name: api-gateway-server
#网关配置
cloud:
gateway:
#路由配置:转发规则
routes:
#id:唯一标识,默认是一个UUID
#uri:转发路径
#predicates:条件,用于请求网关路径的匹配规则
#filters:配置局部过滤器
- id: gateway-provider
uri: http://localhost:8001/
predicates:
- Path=/goods/**
启动测试
三、Gateway网关路由设置
静态路由:上面的入门使用的就是静态路由,因为是uri是写死了的。
注意:在复制routers里面的一条转发规则的时候会出现格式不匹配的坑,一定要在复制粘贴后检查缩进哦!
动态路由:从Eureka中通过服务的名称获取访问的地址,只需要在静态路由基础上修改uri即可
server:
port: 80
spring:
application:
name: api-gateway-server
#网关配置
cloud:
gateway:
#路由配置:转发规则
routes:
#id:唯一标识,默认是一个UUID
#uri:转发路径
#predicates:条件,用于请求网关路径的匹配规则
#filters:配置局部过滤器
- id: gateway-provider
# 静态路由:
# uri: http://localhost:8001/
# 动态路由:
uri: lb://GATEWAY-PROVIDER
predicates:
- Path=/goods/**
- id: gateway-consumer
# uri: http://localhost:9000/
uri: lb://GATEWAY-CONSUMER
predicates:
- Path=/order/**
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
网关中的微服务名称配置:因为我们测试访问的地址时,网关是通过predicates的Path来判断我们访问的是哪个服务,这种方式没办法做到唯一标识。解决办法就是配置微服务名称
server:
port: 80
spring:
application:
name: api-gateway-server
#网关配置
cloud:
gateway:
#路由配置:转发规则
routes:
#id:唯一标识,默认是一个UUID
#uri:转发路径
#predicates:条件,用于请求网关路径的匹配规则
#filters:配置局部过滤器
- id: gateway-provider
# 静态路由:
# uri: http://localhost:8001/
# 动态路由:
uri: lb://GATEWAY-PROVIDER
predicates:
- Path=/goods/**
- id: gateway-consumer
# uri: http://localhost:9000/
uri: lb://GATEWAY-CONSUMER
predicates:
- Path=/order/**
discovery:
locator:
lower-case-service-id: true # 允许为小写
enabled: true # 设置为true 请求路径前可以添加微服务名称
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
注意:discovery这个配置是和routes一个级别的,千万别弄错
四、Gateway网关过滤器
Gateway 支持过滤器功能,对请求或响应进行拦截,完成一些通用操作。
Gateway 提供两种过滤器方式:“pre”和“post”
pre 过滤器,在转发之前执行,可以做参数校验、权限校验、流量监控、日志输出、协议转换等。
post 过滤器,在响应之前执行,可以做响应内容、响应头的修改,日志的输出,流量监控等。
Gateway 还提供了两种类型过滤器
- GatewayFilter:局部过滤器,针对单个路由
- GlobalFilter :全局过滤器,针对所有路由
局部过滤器:filters哈
GatewayFilter 局部过滤器,是针对单个路由的过滤器。
在Spring Cloud Gateway 组件中提供了大量内置的局部过滤器,对请求和响应做过滤操作。
遵循约定大于配置的思想,只需要在配置文件配置局部过滤器名称,并为其指定对应的值,就可以让其生效。
server:
port: 80
spring:
application:
name: api-gateway-server
#网关配置
cloud:
gateway:
#路由配置:转发规则
routes:
#id:唯一标识,默认是一个UUID
#uri:转发路径
#predicates:条件,用于请求网关路径的匹配规则
#filters:配置局部过滤器
- id: gateway-provider
# 静态路由:
# uri: http://localhost:8001/
# 动态路由:
uri: lb://GATEWAY-PROVIDER
predicates:
- Path=/goods/**
filters:
- AddRequestParameter=username,zhangsan
- id: gateway-consumer
# uri: http://localhost:9000/
uri: lb://GATEWAY-CONSUMER
predicates:
- Path=/order/**
discovery:
locator:
lower-case-service-id: true
enabled: true
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
全局过滤器:
GlobalFilter 全局过滤器,不需要在配置文件中配置,系统初始化时加载,并作用在每个路由上。
Spring Cloud Gateway 核心的功能也是通过内置的全局过滤器来完成。
自定义全局过滤器步骤:(其实,局部过滤器也可以这样自定义,但是不大常用,所以不介绍了)
-
定义类实现 GlobalFilter 和 Ordered接口,并复写方法
@Component public class MyFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { System.out.println("自定义过滤器执行了~~~"); return chain.filter(exchange);//放行,让程序继续往下执行 } /** * 过滤器排序 * @return 数值越小 越先执行 */ @Override public int getOrder() { return 0; } }
gateway内置过滤器工厂
这个gateway内置过滤器工厂可以用在过滤器上哦
完成!