赞
踩
每个微服务都需和前端进行通信,解决每个微服务请求时的鉴权、限流、权限校验、跨域等逻辑,放在一个统一的地方进行使用。
在微服务架构中,网关是一个重要的组件,它作为系统的入口,负责接收所有的客户端请求,并将请求路由到相应的微服务。
网关的作用主要有以下几点:
统一入口:网关作为系统的唯一入口,可以为客户端提供一个统一的接口,简化了客户端的调用过程。
路由转发:网关可以根据请求的 URL 和参数等信息,将请求路由到对应的微服务,实现请求的转发。
负载均衡:网关可以通过负载均衡算法,将请求分发到不同的微服务实例上,提高了系统的性能和可用性。
安全控制:网关可以对请求进行鉴权、过滤和监控等操作,保障了系统的安全性和稳定性。
缓存管理:网关可以将一些常用的请求结果进行缓存,减少对后端服务的访问,提高了系统的响应速度。
网关作为流量的入口,常用的功能包括路由转发,权限校验,限流等。
Spring cloud Gateway 是Spring Cloud官方推出的第二代网关框架,定位于取代 Netflix Zuul 1.0来说,Spring Cloud Gateway 提供更优秀的性能,更强大的有功能。使用spring boot 2.0构建。
Spring Cloud Gateway 是由 WebFlux + Nety + Reactor 实现的响应的 API 网关。它不能在传统的 servlet 容器中工作,也不能构建成 war 包。
Spring cloud Gateway 旨在为微服务架构提供种简单且有效的 API路由的管理方式,并基于 Fliter 的方式提供网关的基本功能,例如安全认证、监控、限流等等。
源码:https://github.com/spring-cloud/spring-cloud-gateway
官网文档:https://spring.io/projects/spring-cloud-gateway
特征
Spring Cloud Gateway具有以下特点:
核心概念
1、添加依赖-gateway和nacos
<dependencies>
<!-- spring cloud gateway 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
如果父级有spring-boot-start-web,需删除,删除spring-boot-start-web依赖项。
因为spring cloud gateway是基于webflux的,如果非要web支持的话需要导入spring-boot-starter-webflux而不是spring-boot-start-web。
2、resources/application.yml配置文件配置gateway和nacos
server: port: 8814 spring: application: name: api-gateway #gateway配置 cloud: gateway: #路由规则 routes: # 系统模块 #id 路由的唯一标识 - id: order-service #需要转发的地址 lb:使用 nacos 中本地負載均衡策略 # order-service 服務名 uri: lb://order-service #断言,用于路由规则的匹配,匹配的路径 predicates: - Path=/order-service/** #指定前缀路由 # http://localhost:8814/order-service/order/test 路由到 # http://localhost:8815/order-service/order/test #过滤器,去除一级路径 order-service #最终变成 http://localhost:8815/order/test 进行请求 filters: - StripPrefix=1 #- id #配置nacos nacos: discovery: server-addr: 127.0.0.1:8848 username: nacos password: nacos
也可以简写为:
server: port: 8814 spring: application: name: api-gateway #gateway配置 cloud: gateway: discovery: locator: #启动自动识别nacos服务。即服务名为第一路径 enabled: true #配置nacos nacos: discovery: server-addr: 127.0.0.1:8848 username: nacos password: nacos
请求接口测试:
http://localhost:8814/order-service/order/test
和http://localhost:8815/order/test为一个接口。
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
作用:当请求gateway的时候,使用断言对请求进行匹配,如果匹配成功就路由转发,如果匹配失败就返回404。
类型:内置,自定义。
SpringCloud Gateway包括许多内置的断言工厂,所有这些断言都与HTTP请求的不同属性匹配。具体如下:
1. 基于Datetime类型的断言工厂
此类型的断言根据时间做判断,主要有三个:
AfterRoutePredicateFactory: 接收一个日期参数,判断请求日期是否晚于指定日期。
BeforeRoutePredicateFactory: 接收一个日期参数,判断请求日期是否早于指定日期。
BetweenRoutePredicateFactory: 接收两个日期参数,判断请求日期是否在指定时间段内。
ZonedDateTime.now(); 可以输出当前日期格式。
- After=2023-05-30T00:24:56.119+08:00[Asia/Shanghai]
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
2. 基于远程地址的断言工厂
RemoteAddrRoutePredicateFactory: 接收一个P地址段,判断请求主机地址是否在地址段中。
- RemoteAddr=192.168,1.1/24
3. 基于Cookie的断言工厂
CookieRoutePredicateFactory: 接收两个参数,ookie 名字和一个正则表达式。判断请求cookie是否具有给定名称且值与正则表达式匹配。
-Cookie=chocolate,ch.
4. 基于Header的断言工厂
HeaderRoutePredicateFactory: 接收两个参数,标题名称和正则表达式。判断请求Header是否具有给定名称且值与正则表达式匹配.
-Header=X-Request-Id,\d+
5. 基于Host的断言工厂
HostRoutePredicateFactory: 接收一个参数,主机名模式。判断请求的Host是否满足匹配规则。
- Host=**.somehost.org,**.anotherhost.org
6. 基于路由-常用
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST
- Path=/red/{segment},/blue/{segment}
- Query=green #指定参数
- RemoteAddr=192.168.1.1/24 #指定Ip
7. 基于权重
spring:
cloud:
gateway:
routes:
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8 #分组,80%的权重
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2
8. 自定义路由断言工厂
自定义路由断言工厂需要继承 AbstractRoutePredicateFactory类,重写 apply 方法的逻辑。在apply方法可以通过exchange.getRequest()拿到serverHttpRequest对象,从而可以获取到请求的参数、请求方式、请求头等信息。
步骤:
可以借鉴 QueryRoutePredicateFactory 源码实现自定义的路由断言工厂。
1、代码CheckAuthRoutePredicateFactory
package com.tc.gateway.config; import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.validation.annotation.Validated; import org.springframework.web.server.ServerWebExchange; import javax.validation.constraints.NotEmpty; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; @Component public class CheckAuthRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> { public CheckAuthRoutePredicateFactory() { super(CheckAuthRoutePredicateFactory.Config.class); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList("name"); } @Override public Predicate<ServerWebExchange> apply(CheckAuthRoutePredicateFactory.Config config) { return new GatewayPredicate() { @Override public boolean test(ServerWebExchange exchange) { //简单案例,判断配置文件中CheckAuth是否等于tc if(config.getName().equals("tc")){ return true; } return false; } }; } //用于接收断言中的配置信息 @Validated public static class Config { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } }
2、配置文件。- CheckAuth=tc为自定义的断言信息
server: port: 8814 spring: application: name: api-gateway #gateway配置 cloud: gateway: #路由规则 routes: # 系统模块 #id 路由的唯一标识 - id: order-service #需要转发的地址 lb:使用 nacos 中本地負載均衡策略 # order-service 服務名 uri: lb://order-service #断言,用于路由规则的匹配,匹配的路径 predicates: - Path=/order-service/** #指定前缀路由 # http://localhost:8814/order-service/order/test 路由到 # http://localhost:8815/order-service/order/test # - After=2023-05-30T00:24:56.119+08:00[Asia/Shanghai] #在该时间之前能够访问,之后直接404 # - Header=X-Request-Id,\d+ #需在请求头加入key为X-Request-Id,value为数字 # - Method=GET,POST #请求方式,支持get和post # - Query=name #接口需加入参数?name 案例:http://localhost:8815/order-service/order/test?name # - Query=name,tc|test #限定值只能是tc或者test 案例:http://localhost:8815/order-service/order/test?name=tc - CheckAuth=tc #过滤器,去除一级路径 order-service #最终变成 http://localhost:8815/order/test 进行请求 filters: - StripPrefix=1 #- id #配置nacos nacos: discovery: server-addr: 127.0.0.1:8848 username: nacos password: nacos
gateway 内置了许多的过滤工厂,可以通过过滤工厂进行一些业务逻辑的处理,比如剔除响应头,添加去除参数等。
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
1、局部过滤器
1.1 内置过滤器
内置的过滤器工厂可以在官网进行查看,使用例如:
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: order-service
uri: lb://order-service
filters:
#设置过滤器工厂,给请求头添加默认参数
- AddRequestHeader=X-Request-red, blue
# 添加路径前缀
- PrefixPath=/mypath
1.2 自定义过滤器工厂
和自定义路由断言工厂类似的结构。
package com.tc.gateway.config; import com.alibaba.cloud.commons.lang.StringUtils; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl; /** * @Description: 自定义过滤器工厂 * @Date: 2023/5/31 22:47 */ @Component public class CheckAuthGatewayFilterFactory extends AbstractGatewayFilterFactory<CheckAuthGatewayFilterFactory.Config> { public CheckAuthGatewayFilterFactory() { super(CheckAuthGatewayFilterFactory.Config.class); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList("name"); } @Override public GatewayFilter apply(CheckAuthGatewayFilterFactory.Config config) { return new GatewayFilter() { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { //自己的逻辑处理。简单案例,获取请求中name参数, //如果value=设置的值成功,否则失败 String name = exchange.getRequest().getQueryParams().getFirst("name"); if(StringUtils.isNotEmpty(name)){ if(config.getName().equals(name)){ //正常请求 return chain.filter(exchange); }else{ //返回404 exchange.getResponse().setStatusCode(HttpStatus.NOT_EXTENDED); //结束 return exchange.getResponse().setComplete(); } } return chain.filter(exchange); } }; } public static class Config { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } }
配置文件:
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: order-service
uri: lb://order-service
predicates:
- Path=/order-service/**
filters:
- StripPrefix=1
#自定义的过滤器
- CheckAuth=tc
2.、全局过滤器
授权,权限认证会使用全局过滤器。
自定义全局过滤器
/**
* @Description: 全局过滤器
* @Date: 2023/5/31 23:20
*/
@Component
public class LogFilter implements GlobalFilter {
Logger log = LoggerFactory.getLogger(LogFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("获取请求的地址"+exchange.getRequest().getPath().value());
return chain.filter(exchange);
}
}
测试:
2023-05-31 23:24:04.043 INFO 11244 --- [ctor-http-nio-2] com.tc.gateway.config.LogFilter : 获取请求的地址/order/test
2023-05-31 23:24:04.968 INFO 11244 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty : Flipping property: order-service.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
使用Reactor Netty访问日志
要启用Reactor Netty访问日志,需设置
-Dreactor.netty.http.server.accessLogEnabled=true。
可以在IDEA VM options配置-Dreactor.netty.http.server.accessLogEnabled=true即可。
第二行就是Netty访问日志。
2023-06-01 22:41:27.576 INFO 13052 --- [ctor-http-nio-2] com.tc.gateway.config.LogFilter : 获取请求的地址/order/test
2023-06-01 22:41:27.757 INFO 13052 --- [ctor-http-nio-2] reactor.netty.http.server.AccessLog : 0:0:0:0:0:0:0:1 - - [01/Jun/2023:22:41:26 +0800] "GET /order-service/order/test HTTP/1.1" 200 17 8814 972 ms
2023-06-01 22:41:28.494 INFO 13052 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty : Flipping property: order-service.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
也可以配置到单独的访问日志文件,使用logBack.xml配置。
<appender name="accessLog” class="ch.qos.logback.core.FileAppender">
<file>access_log.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<appender name="async class="ch,qos.logback.classic.AsyncAppender">
<appender-ref ref="accessLog”/>
</appender>
<logger name="reactor.netty.http,server.AccessLog" level="INFO” additivity="false">
<appender-ref ref="async"/>
</logger>
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#cors-configuration
yml配置方式:
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]': #允许跨域访问的资源
allowedOrigins: "https://docs.spring.io" #跨域允许来源
allowedMethods:
- GET
- POST
可以针对不同的路由、接口、或者接口的特征分组限流。
https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81
1、添加依赖
<!-- sentinel整合gateway的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!-- sentinel的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2、添加sentinel配置信息
#配置sentinel
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8858
启动生成网关的一个路由资源:
该路由资源和配置文件中一致:
cloud:
gateway:
#路由规则
routes:
# 系统模块
#id 路由的唯一标识
- id: order-service
通过这个资源即可进行流控。
流控配置界面如下:可以自由灵活配置。
其中API分组流控,即把接口分层不同的Api组,根据组进行流控,分组之后,点击API分组,可以进行选择分好的组。
设置分组界面如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。