赞
踩
Spring Cloud Gateway是Spring公司基于Spring 5.0,Spring Boot 2.0 和 Project Reactor 等术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。它的目标是替代 Netflflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控和限流。
优点:
性能强劲:是第一代网关Zuul的1.6倍
功能强大:内置了很多实用的功能,例如转发、监控、限流等
设计优雅,容易扩展
缺点:
其实现依赖Netty与WebFlux,不是传统的Servlet编程模型,学习成本高
不能将其部署在Tomcat、Jetty等Servlet容器里,只能打成jar包执行
需要Spring Boot 2.0及以上的版本,才支持
路由(Route) 是 gateway 中最基本的组件之一,表示一个具体的路由信息载体。主要定义了下面的几个信息:
id,路由标识符,区别于其他 Route。
uri,路由指向的目的地 uri,即客户端请求最终被转发到的微服务。
order,用于多个 Route 之间的排序,数值越小排序越靠前,匹配优先级越高。
predicate,断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由。
filter,过滤器用于修改请求和响应信息。
创建新的服务
shop-apiGateway-hdw
<!--加入gateway的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
server: port: 7000 spring: application: name: api-gateway # 配置api cloud: gateway: routes: - id: product_route # 路由的唯一标识,只要不重复都可以,如果不写默认会通过UUID产生,一般写成被路由的服务名称 uri: http://localhost:8082/ # 被路由的地址 order: 1 #表示优先级 数字越小优先级越高 predicates: #断言: 执行路由的判断条件 - Path= /product_serv/** filters: # 过滤器: 可以在请求前或请求后作一些手脚 - StripPrefix=1
启动shop-product和shop-apigateway,访问
http://localhost:7000/product_serv/product/productById/2
加入nacos+gateway
<!--加入gateway的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
</dependency>
application.yml
#简写版
server:
port: 7000
spring:
application:
name: api-gateway
# 配置api
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: true
启动类
@SpringBootApplication
@EnableDiscoveryClient //nacos服务发现的注解
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class,args);
}
}
通过网关访问
http://localhost:7000/shop-product/product/productById/3
这时候,就发现只要按照网关地址/微服务/接口的格式去访问,就可以得到成功响应
Predicate(断言, 谓词) 用于进行条件判断,只有断言都返回真,才会真正的执行路由。
断言就是说: 在 什么条件下 才能进行路由转发
基于Datetime类型的断言工厂
此类型的断言根据时间做判断,主要有三个:
AfterRoutePredicateFactory: 接收一个日期参数,判断请求日期是否晚于指定日期
BeforeRoutePredicateFactory: 接收一个日期参数,判断请求日期是否早于指定日期
BetweenRoutePredicateFactory: 接收两个日期参数,判断请求日期是否在指定时间段内
-After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]
基于远程地址的断言工厂 RemoteAddrRoutePredicateFactory:
接收一个IP地址段,判断请求主机地址是否在地址段中
-RemoteAddr=192.168.1.1/24
基于Cookie的断言工厂
CookieRoutePredicateFactory:接收两个参数,cookie 名字和一个正则表达式。 判断请求
cookie是否具有给定名称且值与正则表达式匹配。
-Cookie=chocolate, ch.
基于Header的断言工厂
HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。 判断请求Header是否
具有给定名称且值与正则表达式匹配。
-Header=X-Request-Id, \d+
基于Host的断言工厂
HostRoutePredicateFactory:接收一个参数,主机名模式。判断请求的Host是否满足匹配规则。
-Host=**.testhost.org
基于Method请求方法的断言工厂
MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配。
-Method=GET
基于Path请求路径的断言工厂
PathRoutePredicateFactory:接收一个参数,判断请求的URI部分是否满足路径规则。
-Path=/foo/{segment}基于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
写一个年龄大于18小于60的断言
server: port: 7000 spring: application: name: api-gateway # 配置gateway路由规则 cloud: gateway: discovery: locator: enabled: true # 运行从注册中心拉去服务清单。 # 你的请求地址必须: http://localhost:7000/shop-product/product/findById/1 routes: # 路由: 把客户的符合断言的请求 转发到指定的微服务。 在到达路由前可以适当修改一下请求地址 - id: product-router #路由的唯一标识: 如果没有赋值默认会通过UUID 生成一个唯一标识 uri: lb://shop-product # 路由转发的地址《目的地微服务的地址》 order: 0 # 路由的优先级 值越小优先级越高 predicates: # 断言: 条件 把符合断言的请求 才可以被转发 - Path=/product-serv/** - Age=18,60 #- After=2021-12-31T23:59:59.789+08:00[Asia/Shanghai] filters: # 过滤器: 在到达路由地址前可以对请求地址进行修改 - StripPrefix=1 # 截取请求地址的第一层 # - SetStatus=250 - nacos: discovery: server-addr: http://localhost:8848
import lombok.Data; import org.apache.commons.lang.StringUtils; import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; @Component //AfterRoutePredicateFactory public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> { public static final String DATETIME_KEY = "datetime"; public AgeRoutePredicateFactory() { super(AgeRoutePredicateFactory.Config.class); } // 读取配置文件中内容,把他赋值给Config类的属性 public List<String> shortcutFieldOrder() { return Arrays.asList("minAge","maxAge"); } // 断言的业务逻辑 public Predicate<ServerWebExchange> apply(AgeRoutePredicateFactory.Config config) { return new Predicate<ServerWebExchange>() { @Override public boolean test(ServerWebExchange serverWebExchange) { //获取请求地址的age参数值. //localhost:8001/findbyid?age=18&name=zs&age=18 String age = serverWebExchange.getRequest().getQueryParams().getFirst("age"); if(StringUtils.isNotEmpty(age)){ if(Integer.parseInt(age)>=config.getMinAge()&&Integer.parseInt(age)<=config.getMaxAge()){ return true; } } return false; } }; } @Data public static class Config { private Integer minAge; private Integer maxAge; } }
访问
http://localhost:7000/product-serv/product/productById/2?age=30
api网关开启,直接访问controller中RequestMapping路径
server: port: 7000 spring: application: name: api-gateway # 配置gateway路由规则 cloud: gateway: discovery: locator: enabled: true # 运行从注册中心拉去服务清单。 # 你的请求地址必须: http://localhost:7000/shop-product/product/findById/1 routes: # 路由: 把客户的符合断言的请求 转发到指定的微服务。 在到达路由前可以适当修改一下请求地址 - id: product-router #路由的唯一标识: 如果没有赋值默认会通过UUID 生成一个唯一标识 uri: lb://shop-product # 路由转发的地址《目的地微服务的地址》 order: 0 # 路由的优先级 值越小优先级越高 predicates: # 断言: 条件 把符合断言的请求 才可以被转发 # - Path=/product-serv/** - Age=18,60 #- After=2021-12-31T23:59:59.789+08:00[Asia/Shanghai] # filters: # 过滤器: 在到达路由地址前可以对请求地址进行修改 # - StripPrefix=1 # 截取请求地址的第一层 # - SetStatus=250 - nacos: discovery: server-addr: http://localhost:8848
依赖导入
<!--引入spring-cloud-gateway和sentinel整合的jar 网关限流-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
修改yml配置文件
server: port: 7000 spring: application: name: api-gateway # 配置gateway路由规则 cloud: gateway: discovery: locator: enabled: true # 运行从注册中心拉去服务清单。 # 你的请求地址必须: http://localhost:7000/shop-product/product/findById/1 routes: # 路由: 把客户的符合断言的请求 转发到指定的微服务。 在到达路由前可以适当修改一下请求地址 - id: product-router #路由的唯一标识: 如果没有赋值默认会通过UUID 生成一个唯一标识 uri: lb://shop-product # 路由转发的地址《目的地微服务的地址》 order: 0 # 路由的优先级 值越小优先级越高 predicates: # 断言: 条件 把符合断言的请求 才可以被转发 - Path=/product-serv/** # - Age=18,60 #- After=2021-12-31T23:59:59.789+08:00[Asia/Shanghai] filters: # 过滤器: 在到达路由地址前可以对请求地址进行修改 - StripPrefix=1 # 截取请求地址的第一层 # - SetStatus=250 - nacos: discovery: server-addr: http://localhost:8848
写网关配置类
@Configuration public class GatewayConfiguration { private final List<ViewResolver> viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) { this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); this.serverCodecConfigurer = serverCodecConfigurer; } /** * 配置限流的异常处理器:SentinelGatewayBlockExceptionHandler */ @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); } /** * 配置限流过滤器 */ @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public GlobalFilter sentinelGatewayFilter() { return new SentinelGatewayFilter(); } /** * 配置初始化的限流参数 */ @PostConstruct public void initGatewayRules() { Set<GatewayFlowRule> rules = new HashSet<>(); rules.add(new GatewayFlowRule("product_service") //资源名称 .setCount(1) // 限流阈值 .setIntervalSec(1) // 统计时间窗口,单位是秒,默认是 1 秒 ); GatewayRuleManager.loadRules(rules); } }
基于Sentinel 的Gateway限流是通过其提供的Filter来完成的,使用时只需注入对应的SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例即可。
@PostConstruct定义初始化的加载方法,用于指定资源的限流规则。这里资源的名称为 order-service ,统计时间是1秒内,限流阈值是1。表示每秒只能访问一个请求。
多次访问http://localhost:7000/product_service/product/findById/2,发现被限流
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。