1.springcloudAlibaba-nacos
2.springcloudAlibaba-openFeign
3.springcloudAlibaba-负载均衡器Ribbon
4.springcloudAlibaba-nacos配置中心
5.springcloudAlibaba-Seata 分布式事务
6.springcloudAlibaba-sentinel
7.springcloudAlibaba-网关gateway
目录
网关介绍
核心概念
Spring Cloud Gateway快速开始
集成Nacos
路由断言工厂
过滤器工厂( GatewayFilter Factories)配置
全局过滤器(Global Filters)配置
Reactor Netty 访问日志
Gateway跨域配置(CORS Configuration)
在微服务中存在很多服务,前端需要每个服务都维护一个ip,如果搭建集群 更是头疼,再比如鉴权、限流、日志、跨域等问题,都需要每个服务配一下,所以就衍生出网关来进行统一处理,就像家里的大门,所有人都走大门,收快递,防盗 都要在门口处理
Spring Cloud GateWay是Spring Cloud的一个全新项目,目标是取代Netflix Zuul,它基于 Spring5.0+SpringBoot2.0+WebFlux(基于高性能的Reactor模式响应式通信框架Netty,异步非阻塞模 型)等技术开发,性能高于Zuul,官方测试,GateWay是Zuul的1.6倍,旨在为微服务架构提供一种简 单有效的统一的API路由管理方式。
Spring Cloud GateWay不仅提供统一的路由方式(反向代理)并且基于 Filter(定义过滤器对请求过滤, 完成一些功能) 链的方式提供了网关基本的功能,例如:鉴权、流量控制、熔断、路径重写、日志监控 等。
基于Spring Framework 5, Project Reactor 和 Spring Boot 2.0 进行构建;
动态路由:能够匹配任何请求属性;
支持路径重写;
集成 Spring Cloud 服务发现功能(Nacos、Eruka);
可集成流控降级功能(Sentinel、Hystrix);
可以对路由指定易于编写的 Predicate(断言)和 Filter(过滤器)
路由(route)
路由是网关中最基础的部分,路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。如果断言为真,则说明请求的URL和
配置的路由匹配。
断言(predicates)
Java8中的断言函数,SpringCloud Gateway中的断言函数类型是Spring5.0框架中的ServerWebExchange。断言函数允许开发者去定义
匹配Http request中的任何信息,比如请求头和参数等。
过滤器(Filter)
SpringCloud Gateway中的filter分为Gateway FilIer和Global Filter。Filter可以对请求和响应进行处理
新建modules springcloud-gateway
添加依赖
org.springframework.cloud spring-cloud-starter-gateway
新增启动类
新增application.yml
server: port: 8881 spring: application: name: springcloud-gateway cloud: gateway: routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务] - id: product_route # 当前路由的标识, 要求唯一 uri: http://localhost:9999 # 请求要转发到的地址 order: 1 # 路由的优先级,数字越小级别越高 predicates: # 断言(就是路由转发要满足的条件) - Path=/gateway/** # 当请求路径满足Path指定的规则时,才进行路由转发 filters: - StripPrefix=1 #转发之前去掉1层路径
这里我们请求http://localhost:8881/gateway/orderController/getInfo
gateway拿到这个地址 截取到 /gateway/ 然后转发到 uri地址 在转发之前 filters会 去掉第一次路径
我们在启动 之前的order module
可以看到 通过gateway 分发到了该服务上
引入依赖
com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery
修改application.yml
加入nacos 配置 将本服务注册到nacos
uri 就可以直接修改为服务名,同时加入nacos的负载均衡策略
server: port: 8881 spring: application: name: springcloud-gateway cloud: nacos: server-addr: 49.232.193.91:8848 username: nacos password: nacosnacos gateway: routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务] - id: product_route # 当前路由的标识, 要求唯一 uri: lb://order-service # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略 order: 1 # 路由的优先级,数字越小级别越高 predicates: # 断言(就是路由转发要满足的条件) - Path=/gateway/** # 当请求路径满足Path指定的规则时,才进行路由转发 filters: - StripPrefix=1 #转发之前去掉1层路径
再次请求http://localhost:8881/gateway/orderController/getInfo
效果是一样的
同时gateway也提供了一种默认配置
实现方式也很简单 如下
server: port: 8881 spring: application: name: springcloud-gateway cloud: nacos: server-addr: 49.232.193.91:8848 gateway: discovery: locator: enabled: true
等同于
gateway: routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务] - id: product_route # 当前路由的标识, 要求唯一 uri: lb://order-service # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略 order: 1 # 路由的优先级,数字越小级别越高 predicates: # 断言(就是路由转发要满足的条件) - Path=/order-service/** # 当请求路径满足Path指定的规则时,才进行路由转发 filters: - StripPrefix=1 #转发之前去掉1层路径
gateway提供了很多断言方式,具体可以看一下官网说明跟样例,这里简单介绍几个
官网地址:Spring Cloud Gateway
作用:当请求gateway的时候, 使用断言对请求进行匹配, 如果匹配成功就路由转发, 如果匹配失败就返回404
基于Datetime类型的断言工厂
此类型的断言根据时间做判断,主要有三个:
AfterRoutePredicateFactory: 接收一个日期参数,判断请求日期是否晚于指定日期
BeforeRoutePredicateFactory: 接收一个日期参数,判断请求日期是否早于指定日期
BetweenRoutePredicateFactory: 接收两个日期参数,判断请求日期是否在指定时间段内
ZonedDateTime.now()
‐ After=2019‐12‐31T23:59:59.789+08:00[Asia/Shanghai]
基于远程地址的断言工厂
RemoteAddrRoutePredicateFactory:接收一个IP地址段,判断请求主机地址是否在地址
‐ RemoteAddr=192.168.1.1/24
基于Header的断言工厂
HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。 判断请求Header是否具有给定名称且值与正则表达式匹配
‐Header=X‐Request‐Id, \d+
基于Host的断言工厂
HostRoutePredicateFactor:接收一个参数,主机名模式。判断请求的Host是否满足匹配
‐Host=**.testhost.org
基于Method请求方法的断言
MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配
‐Method=GET
基于Query请求参数的断言工厂
QueryRoutePredicateFactory :接收两个参数,请求param和正则表达式, 判断请求参数是否具有给定名称且值与正则表达式匹配
‐Query=baz, ba.
基于路由权重的断言工厂
WeightRoutePredicateFactory:接收一个[组名,权重], 然后对于同一个组内的路由按照权重转发
routes: ‐id: weight_route1 uri: host1 predicates: ‐Path=/product/** ‐Weight=group3, 1 ‐id: weight_route2 uri: host2 predicates: ‐Path=/product/** ‐Weight= group3, 9
这些基本上开发使用够用了,同事也提供了自定义断言方式 有兴趣可以了解一下
大体修改方式大同小异
像 AddRequestParameter 添加参数 、 PrefixPath为匹配的路由统一添加前缀 、‐ Redirect 重定向 还是用的挺多的 同事也提供了自定义过滤器
过滤器工厂 |
作用 |
参数 |
AddRequestHeader |
为原始请求添加Header |
Header的名称及值 |
AddRequestParameter |
为原始请求添加请求参数 |
参数名称及值 |
AddResponseHeader |
为原始响应添加Header |
Header的名称及值 |
DedupeResponseHeader |
剔除响应头中重复的值 |
需要去重的Header名称及去重策略 |
Hystrix |
为路由引入Hystrix的断路器保护 |
Hystrixcommand的名称 |
FallbackHeaders |
为fallbackUri的请求头中添加具体的异常信息 |
Header的名称 |
PrefixPath |
为原始请求路径添加前缀 |
前缀路径 |
PreserveHostHeader |
为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host |
无 |
RequestRateLimiter |
用于对请求限流,限流算法为令牌桶 |
keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus |
RedirectTo |
将原始请求重定向到指定的URL |
http状态码及重定向的url |
RemoveHopByHopHeadersFilter |
为原始请求删除IETF组织规定的一系列Header |
Header名称 |
RemoveResponseHeader |
为原始请求删除某个Header |
Header的名称 |
RewritePath |
重写原始的请求路径 |
原始路径正则表达式以及重写后路径的正则表达式 |
RewriteResponseHeader |
重写原始响应中的某个Header |
Header名称,值的正则表达式,重写后的值 |
SaveSession |
在转发请求之前,强制执行websession::save操作 |
无 |
secureHeaders |
为原始响应添加一系列起安全作用的响应头 |
无,支持修改这些安全响应头的值 |
SetPath |
修改原始的请求路径 |
修改后的路径 |
SetResponseHeader |
修改原始响应中某个Header的值 |
Header名称,修改后的值 |
SetStatus |
修改原始响应的状态码 |
HTTP状态码,可以是数字,也可以是字符串 |
StripPrefix |
用于截断原始请求的路径 |
使用数字表示要截断的路径的数量 |
Retry |
针对不同的响应进行重试 |
retries、statuses、methods、 series |
RequestSize |
设置允许接收最大请求包的大小。如果请求包大小超过设置的值,则返413Payload Too Large |
请求包大小,单位为字节,默认值为5M |
ModifyRequestBody |
在转发请求之前修改原始请求体内容 |
修改后的请求体内容 |
ModifyResponseBody |
修改原始响应体的内容 |
修改后的响应体内容 |
局部过滤器和全局过滤器区别:
局部:局部针对某个路由, 需要在路由中进行配置
全局:针对所有路由请求, 一旦定义就会投入使用
GlobalFilter 接口和 GatewayFilter 有一样的接口定义,只不过, GlobalFilter 会作用于所有路由
package oo.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class LogFilter implements GlobalFilter { Logger log = LoggerFactory.getLogger(this.getClass()); @Override public Monofilter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info(exchange.getRequest().getPath().value()+"-----------------"); return chain.filter(exchange); } }
要启用 Reactor Netty 访问日志,请设置Dreactor.netty.http.server.accessLogEnabled=true.
它必须是 Java 系统属性,而不是 Spring Boot 属性。
您可以将日志记录系统配置为具有单独的访问日志文件。以下示例创建一个 Logback 配置:
access_log.log %msg%n
globalcors: cors-configurations: '[/**]': allowCredentials: true #springboot2.4后需用allowedOriginPatterns allowedOriginS: "*" allowedMethods: "*" allowedHeaders: "*"