gateway核心概念
- 路由(route)
路由是网关中最基础的部分,路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。如果断言为真,则说明请求的URL 和 配置的路由匹配。 - 断言(predicates)
断言函数允许 开发者去定义匹配 Http request中的任何信息,比如请求头和参数等。
3.过滤器(Filter)
Filter分为Gateway FilIer和Global Filter。Filter可以对请求和响应进行处理。
gateway快速开始
1. 引入依赖
注意:会和spring-webmvc的依赖冲突,需要排除spring-webmvc
2.编写yml配置文件
server.port = 8088是 网关的访问端口
spring.application.name 是 当前网关服务的服务名称
gateway.routes下面定义路由规则:
id是这个路由规则的名称,gateway.routes下面可以有很多的路由规则
url :把访问当前网关的这个服务, 转发到哪个url去,首先,我不能什么请求到网关都去转发,需要满足一定的条件,predicates断言,就是起到这个作用
predicates:当 请求到了当前这个网关 (那么 这个请求就必须带了当前网关的 ip+端口号 的信息,后面紧跟着 斜杠 / ,所以网关可以默认这些信息是有的, predicates中不用考虑这些信息 ), 如果 端口号后面的url,以 /order-serv/** 开头 ,那么 就转发到 上面url的 ip + 端口 。 并且斜杠 / 后面的所有路径都不会去掉,那么就转发到了http://localhost:8020/order-serv/order/add 这个地址
(order-serv是服务名称,防止订单服务里有/order/add开头的地址,库存服务里也有/order/add开头的地址,所以 发到gateway的请求,都带上需要转发到的服务的名称 ),但是 订单服务 里 接收的请求里 是 没有 /order-serv/的 ,只有发来的请求是 http://localhost:8020/order/add ,才能进行接收, 所以 让网关把 第一层路径给去掉,通过 filters 过滤前缀
如果不满足断言,就会报 404 的 错误
这里我们在配置里把转发的url地址都写死,当服务器发生迁移,ip地址会变动 或者 服务器是以集群的形式部署的,还需要通过nginx来进行反向代理和负载均衡,很麻烦。
我们通过把gateway和nacos集成起来,就可以轻松解决这些问题
集成Nacos
1. 继续引入nacos的依赖
2. 继续编写yml配置文件
(1)集成nacos,只需将当前的gateway服务,注册到nacos上即可,写上nacos服务地址和账号密码
(2)将路由规则中的,转发到哪个服务的地址,改成服务名称 "order-service" 即可(url: order-service),又因为需要使用nacos自带的ribbon的负载均衡策略,所以前面加上 lb:// , lb的意思是loadbalance负载均衡。
gateway网关会将 "order-service" 整体 替换成 其中一个 订单服务的 ip 地址(因为网关会定时拉取各种nacos上注册上去的服务的ip地址列表)
这样就解决了当服务器发生迁移,ip地址变动 或者 服务器是以集群的形式部署的,还需要通过nginx来进行反向代理和负载均衡的问题
简写路由规则:约定大于配置
(1)开启自动识别nacos服务的功能后,就不需要写断言规则了
(2)将发送到网关的请求 ,以注册到nacos上的服务名称开头时,会自动转发到那个服务的某个服务器上,并自动过滤掉第一层路径(缺点:路由规则不够灵活)
这时候,只要按照网关地址/微服务/接口的格式去访问,就可以得到成功响应。
断言工厂
根据url来进行断言,是gateway内置的断言工厂
自定义路由断言工厂
这里假设自定义一个基于Query请求参数的断言工厂,复制源码里面的内容,然后根据需要进行修改
自定义 一个基于Query请求参数的断言工厂, 需要继承 AbstractRoutePredicateFactory 类,重写 apply 方法的逻辑。在 apply 方法中可以通过 exchange.getRequest() 拿到 ServerHttpRequest 对象,从而可以获取到请求的参数、请求方式、请求头等信息。
- 必须是spring组件 ,即是一个bean
- 类必须加上 RoutePredicateFactory 作为结尾
- 必须继承 AbstractRoutePredicateFactory
- 必须声明静态内部类,声明属性来接收 配置文件中对应的断言的信息
- 需要结合 shortcutFieldOrder 进行绑定
- 通过apply进行逻辑判断 true就是匹配成功 false匹配失败
过滤器(先过滤再路由)
(1)先经过 过滤器 把请求的url地址处理后,或者添加删除修改一些请求头、cookie等的信息,
(2)再通过nacos的服务列表进行路由到 对应的服务器上
过滤器的作用:当一个请求来到gateway网关时,我们可以对这个请求进行一个业务逻辑的处理。
比如:
(1)前面通过 过滤器 去把第一层路径给去掉
(2)可以给来到网关的所有请求添加一个请求头,再设置里面的内容。
(3)可以给来到网关的所有请求设置一个cookie等等处理
具体全部内置的过滤器有哪些可以访问官网
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
下面是一些代码示例:
测试地址是发送给gateway网关的
通过routes路由到下面的@GetMapping的地址,下面的代码来接收请求和进行响应
例1:
例2
例3
前一个url地址是发送到网关的,经过过滤器,加上了前缀/mall-order。这时,服务端要能接收响应,必须设置,发送来的请求,都带上/mall-order。这样服务器才能进行正常的接收网关路由来的请求
例4
发送到当前网关的请求,都会被路由到百度网站
302是重定向之后的响应状态码
自定义过滤器
全局过滤器
局部过滤器和全局过滤器区别:
局部:局部针对某个路由, 需要在路由中进行配置
全局:针对所有路由请求, 不需要在配置文件中配置, 一旦定义就会投入使用
内置的全局过滤器:
路由地址中带了lb的话,就会自动采用负载均衡策略,和上面第一个的全局过滤器对应
这些全局过滤器 会自动判断,自动处理,不用我们管理
自定义全局过滤器(重点)
记录所有访问过来的请求,保存成日志的形式,可以用自定义全局过滤器
或者判断用户登录、权限方面也可以自定义全局过滤器
自定义全局过滤器非常简单
- 定义一个类,交给springIOC容器管理,即加上spring的注解 @Compenent
- 继承GlobalFilter接口,重写里面的filter方法,只需要写里面的方法体就行
- 参数exchange 里面 包含了 进入网关的 这个 请求的所有信息 ,取出url地址,header头、cookies,路径参数等等所有信息都可以,然后进行相应的 业务处理
- return chain.filter(exchange) 将请求进行放行
请求日志记录
在网关微服务里,在这个地方加上这个命令,可以开启日志记录,将所有通过网关的请求,都记录下来,不过只是输出到控制台
gateway跨域配置
跨域:当http请求 不在 同一个ip+同一个端口时,就叫做跨域
(只有同一个ip+同一个端口才叫 同域,两个都满足才同域)
- 通过yml配置的方式 ,配置在gateway的下一级
配置的内容可以自己修改跨域
2. 通过配置类的方式设置
sentinel结合gateway网关
结合sentinel对发送到gateway网关的请求,进行流控降级
sentinel分为两个部分
前提:远程服务器下载sentinel客户端,安装、运行后
gateway服务只需:
gateway服务的配置文件加上sentinel客户端的ip+端口、账号密码
这样就整合好了sentinel的流控降级
sentinel针对gateway网关服务有特殊的规则,它的界面和 对于controller中方法(服务入口)的流控降级界面不太一样
可以针对断言工厂里面的这些规则进行限流
可以针对某个ip、远程域名、请求头、url中的参数、cookie值进行限流
自定义sentinel结合网关 后的响应内容
在网关层被sentinel流控降级或者熔断后,会响应下面的内容给发送请求者,
这样的内容如果不是我们想要的,就需要自定义响应异常的方式。有两种方式
方式1:(简单)
在yml配置中,分层写上面的内容,
spring . cloud . sentinel . scg . fallback . response ‐ body = '{"code":403,"mes":" 限流了 "}'
response‐body后面的内容就是我们自定义的响应内容(json格式的) ,写的内容就是响应的内容
方式2:
设置响应状态码、响应类型(json格式的)、响应内容("降级了!")
网关高可用