文章目录
spring-cloud-Hoxton.SR6 (十)网关-GateWay
本文spring-cloud 版本为:hoxton.sr6
本文spring-boot版本为:2.2.x-2.3.x
在前边我们已经讲过了为什么要使用网关,已经网关组件zuul的使用
目前zuul组件已经从1.0更新到2.0,但是作为springcloud官方不再推荐使用zuul2.0,但也依然支持zuul2.
随着其cloud版本的不断升级,其官方自己研发出了一款新兴网关组件:GateWay
(一)简单了解什么是GateWay?
# 官方解释
- https://spring.io/projects/spring-cloud-gateway
- 这个项目提供了一个在springmvc之上构建API网关的库。springcloudgateway旨在提供一种简单而有效的方法来路由到api,并为api提供横切关注点,比如:安全性、监控/度量和弹性。
# 特点
- 基于springboot2.x 和 spring webFlux 和 Reactor 构建 响应式异步非阻塞IO模型
- 动态路由
- 请求过滤
(二)Gateway的使用
(1)五分钟入门
①搭建gateway微服务
按照常理引入所需依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--consul客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--gateway核心依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--consul中健康检查需要用到actuator,不添加会check failing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
consul依赖(网关也是需要注册到咱们注册中心的,我们呢,还是使用consul作为注册中心)
gateway依赖: 使用gateway功能必要的依赖
web依赖:(网关也需要作为一个服务进行启动,其服务只负责网关功能,不处理其余业务逻辑,需要注意的是,gateway 依赖实际与web存在着冲突,同时引入依赖会导致项目无法启动,这里在下边也会讲到)
②基本配置
首先,我们将其作为一个最基础的服务,连接consul注册中心先
server:
port: 6001 #端口
spring:
application:
#服务名称
name: app-gateway
###开始配置consul的服务注册
cloud:
consul:
#consul服务器的主机地址 默认:localhost
host: localhost
#consul服务器的ip地址 默认:8500
port: 8500
discovery:
#是否需要注册
register: true
#注册的实例ID (唯一标志)
instance-id: ${spring.application.name}-1
#服务的名称
service-name: ${spring.application.name}
#当前服务的请求端口
port: ${server.port}
#指定开启ip地址注册
prefer-ip-address: true
#当前服务所在 ip ${spring.cloud.client.ip-address}
ip-address: ${spring.cloud.client.ip-address}
尝试启动,看看是否能注册到consul注册表中
启动报错
**********************************************************
Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. Please remove spring-boot-starter-web dependency.
**********************************************************
根据提示,需要我们移除掉web依赖
再次启动 —成功
为什么gateway需要移除掉web依赖才能启动呢?
答:gateway为了效率使用webflux进行异步非阻塞模型的实现,和web包存在冲突,因此如果某项目引入了gateway依赖,需要去除掉去掉web依
(2)Gateway相关功能
我们前边gateway网关项目已经搭建好了,但是呢,我们并没有配置任何gateway相关的东西,接下来咱们就一 一演示
在演示前呢,我们依旧先启动之前编写的几个服务,还是模拟访问这些服务
①简单的路由功能
首先,我们需要进行路由配置,其思路,与zuul也是一样的,我们接下来会对比着进行配置
gateway配置格式更特别,在properties中无法得心应手的使用,需要使用yml格式
spring:
application:
#服务名称
name: app-gateway
cloud:
gateway:
routes:
#最普通的路由
- id: easy-order
uri: http://localhost:9002/
predicates:
- Path=/order/**
先看功能,再解释
通过访问网关的http://localhost:6001/order/demo
接口调用到了 order服务 localhost:9002/order/demo
接口
但是呢,现有路由配置方式,都是基于服务地址写死的路由转发,我们能不能根据服务名称进行路由转发同时实现负载均衡的呢?
当时是可以的,我们放在案例④讲解,接下来呢,咱们进行配置分析
②gateway路由配置解释与zuul路由配置对比
zuul的路由配置 routes呢,为map
我们点进 ZuulRoute
类去查看详细字段配置信息
gateway 路由配置routes呢,为List
因为其为list 所以在yml配置中,每一个完整的RouteDefinition
元素前都需要加 - 符号
我们再点击RouteDefinition
路由配置元素中看字段,发现其中与zuul路由字段有点大同小异
常用配置解释:
id: 固定配置前缀,当前路由配置名(自定义名字即可),在整个网关理由配置中,需保证该路由名唯一
uri: 固定配置前缀,当前路由触发后,需要转发到哪里
predicates: 固定配置前缀,路由谓词工厂(即什么条件满足后触发当前路由,明细在下文会详细讲到)
filters: 固定配置前缀,路由过滤 可路有前过滤,路由后过滤,明细在下文会讲到
那么,结合以上呢,可以来仔细罗列路由配置差异了!
此二者路由配置较为等价,但访问方式不同
虚假的相等
方式方式不同原因如下:
不知道各位小伙伴是否还记得我在zuul篇中提到过,zuul网关路由配置时,默认在路由转发的时候,将路由前缀去掉了的
源码注释如下:
用于确定在转发之前是否应删除此路由的前缀
什么意思呢
就是如按照上图的zuul的配置 我如果要访问order服务的/order/demo
接口,我如果是走zuul网关的话,那么访问路径为 localhost:6001/order/order/demo
匹配到路由规则path :/order/**后 开始路由,并去除请求前缀,实际请求转发到了localhost:9002/order/demo
而我们的gateway组件呢,默认是没有去除路由前缀的,即如果你访问 localhost:6001/order/order/demo
,匹配到路由规则(路由谓词)predicates
predicates:
- Path=/order/**
后呢,开始路由,但并不会去除前缀order 因此转发到9002请求为localhost:9002/order/order/demo
因此呢,如果要使上方二者路由规则完全一致,且访问方式一则,则zuul需要作出改变,或gateway需要添加去除请求前缀配置
真正的相等
zuul 设置不移除请求前缀
gateway请求前缀处理: 放在下边讲…
至于如何处理请求前缀,需要根据项目Url 来自行判断了,我仅仅是告诉你两种处理方式,具体如何处理,君请自便了呀!
③ 路由配置规则
匹配规则: 即路径配置规则
通配符 | 说明 | 演示 |
---|---|---|
* | 不支持多级目录 | /order/*、/order/zs 、order/aaa |
** | 支持多级目录 | s/order/**、 /order/zs/li/wangwu/aa/cc |
④根据服务名进行路由 负载均衡调用
在微服务中,且各个服务使用的是同一个注册中心或注册中心集群,服务间调用是通过服务名进行的,从而到达负载均衡调用的效果
我们的gateway呢,与zuul一样,同样也是支持网关调用服务负载均衡的
配置如下:
server:
port: 6001 #端口
spring:
cloud:
gateway:
routes:
#最普通的路由
- id: easy-order
uri: http://localhost:9002/
predicates:
- Path=/order/**
#服务名路由 负载均衡
- id: server-product
uri: lb://demo-product
predicates:
- Path=/product/**
可以看出,服务名路由与指定服务的端口Ip路由唯一不同的区别仅仅就是 路由的uri
的配置
uri: lb://demo-product详解
lb: lb是英文(loadbalance)的缩写,注意前边是小写的L,不是阿拉伯数字1
//demo-product //为固定写法,后边跟上需要转发到哪个服务的服务名
写法演示示例:uri: lb://服务名
如果服务名配置无效,那么你需要在yml中,额外再配置一句
spring.cloud.gateway.discovery.locator.enabled=true
yml写法:
spring:
cloud:
gateway:
routes:
#服务名路由 负载均衡
- id: server-product
uri: lb://demo-product
predicates:
- Path=/product/**
# 启用DiscoveryClient网关集成的标志,如果服务名路由无效时,可设置后再次尝试
discovery:
locator:
enabled: true
⑤java代码进行路由配置
gateway也是同样支持java代码进行路由配置的,其语句我感觉就是直接将yml配置照搬到了java中,,很是方便上手…
我们先注释掉yml配置
java代码配置路由信息
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author lei
* @version 1.0
* @date 2020/10/12 21:25
* @desc gateway网关java配置路由信息,这里仅做简单演示了,详情可查官网
*/
@Configuration
public class GateWayRouteConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("easy-order", r -> r.path("/order/**")
.uri("http://localhost:9002/"))
.route("server-product", r -> r.path("/product/**")
.uri("lb://demo-product"))
.build();
}
}
…综上,便是Gateway的简单使用了
下一篇:GateWay强大的路由谓词(断言)功能