GateWay服务限流
秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行.flowlimit
Gateway
Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和 Project Reactor等技术。
Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,例如:熔断、限流、重试等。
![1596980807123]()
SpringCloud Gateway 使用的是Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。
![1596981084802]()
![1596981218641]()
![1596982261551]()
Gateway:
![1596982457962]()
Gateway的三大核心概念
Route(路由)
路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由。
Predicate(断言)
参考的是java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
Filter(过滤)
指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
![1597041510243]()
工作流程
![1597041530900]()
核心逻辑
路由转发+执行过滤器链
新建cloud-gateway-gateway9527
pom(移除了web依赖)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>com.kayleh.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
|
yml
1 2 3 4 5 6 7 8 9 10 11 12 13
| server: port: 9527 spring: application: name: cloud-gateway eureka: instance: hostname: cloud-gateway-service client: service-url: register-with-eureka: true fetch-registry: true defaultZone: http://eureka7001.com:7001/eureka
|
无业务类
主启动类
1 2 3 4 5 6 7 8
| package com.kayleh.springcloud; @SpringBootApplication @EnableEurekaClient public class GateWayMain9527 { public static void main(String[] args) { SpringApplication.run(GateWayMain9527.class, args); } }
|
观察cloud-provider-payment8001的controller的get/lb访问路径
目前不想暴露8001端口,希望在8001外面套一层9527
修改pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| server: port: 9527 spring: application: name: cloud-gateway cloud: gateway: routes: - id: payment_routh uri: http://localhost:8001 predicates: - Path=/payment/get/**
- id: payment_routh2 uri: http://localhost:8001 predicates: - Path=/payment/lb/**
eureka: instance: hostname: cloud-gateway-service client: service-url: register-with-eureka: true fetch-registry: true defaultZone: http://eureka7001.com:7001/eureka
|
测试
添加网关前
1
| http://localhost:8001/payment/get/31
|
添加网关后
1
| http://localhost:9527/payment/get/31
|
![1597043412245]()
除了使用yaml的方法配置还可以使用代码配置:9527
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.kayleh.springcloud.config;
@Configuration public class GateWayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) { RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes(); routes.route("path_rote_kayleh", r -> r.path("/guonei") .uri("http://news.baidu.com/guonei")).build(); return routes.build(); } }
|
测试
1
| http://localhost:9527/guonei
|
通过微服务名实现动态路由
默认情况下Gateway会根据注册中心的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能
修改yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| server: port: 9527 spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true routes: - id: payment_routh uri: lb://cloud-payment-service predicates: - Path=/payment/get/**
- id: payment_routh2 uri: lb://cloud-payment-service predicates: - Path=/payment/lb/**
eureka: instance: hostname: cloud-gateway-service client: service-url: register-with-eureka: true fetch-registry: true defaultZone: http://eureka7001.com:7001/eureka
|
需要注意的是uri的协议为lb,表示启用Gateway的负载均衡功能。
lb://serviceName是spring cloud gateway在微服务中自动为我们创建的负载均衡uri
测试
1
| http://localhost:9527/payment/lb
|
8001/8002两个端口切换
Predicate的使用
![1597054276153]()
![1597054330113]()
![1597054313552]()
![1597054346178]()
常用的Route Predicate
After Route Predicate
1 2
| - After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
|
时间可以这样获取:
1 2
| ZonedDateTime zbj = ZonedDateTime.now(); System.out.println(zbj);
|
Before Route Predicate
1 2
| - After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] - Before=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
|
Between Route Predicate
1
| - Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] , 2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
|
Cookie Route Predicate
![1597054584109]()
1
| - Cookie=username,kayleh
|
![1597054626731]()
不带cookies访问
1 2 3 4 5
| -> cmd curl http://localhost:9527/payment/lb
curl http://localhost:9527/payment/lb --cookie "username,kayleh" #返回端口号表示访问成功
|
带上cookies访问
加入curl返回中文乱码
https://blog.csdn.net/leedee/article/details/82685636
1
| - Header=X-Request-Id, \d+
|
![1597054747638]()
![1597054756074]()
Host Route Predicate
Method Route Predicate
Path Route Predicate
Query Route Predicate
1
| - Query=username, \d+ #要有参数名称并且是正整数才能路由
|
测试
1 2
| curl http://localhost:9527/payment/lb?username=1 curl http://localhost:9527/payment/lb?username=-1
|
ALL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| server: port: 9527 spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true routes: - id: payment_routh uri: lb://cloud-payment-service predicates: - Path=/payment/get/** - id: payment_routh2 uri: lb://cloud-payment-service predicates: - Path=/payment/lb/** eureka: instance: hostname: cloud-gateway-service client: service-url: register-with-eureka: true fetch-registry: true defaultZone: http://eureka7001.com:7001/eureka
|
说白了,Predicate就是为了实现一组匹配规则,
让请求过来找到对应的Route进行处理
Filter
是什么?
![1597068671697]()
生命周期
pre 在业务逻辑之前
post 在业务逻辑之后
种类
GatewayFilter 单一
GlobalFilter 全局
常用的GatewayFilter
AddRequestParameter
yml:
![1597068815115]()
自定义过滤器
自定义全局GlobalFilter
两个主要接口介绍
impiemerts GlobalFilter ,Ordered
能干嘛
全局日志记录
统一网关鉴权
。。。
案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package com.kayleh.springcloud.filter;
import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono;
import java.util.Date;
@Component @Slf4j public class MyLogGateWayFilter implements GlobalFilter,Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("*********come in MyLogGateWayFilter: "+new Date()); String uname = exchange.getRequest().getQueryParams().getFirst("username"); if(StringUtils.isEmpty(username)){ log.info("*****用户名为Null 非法用户,(┬_┬)"); exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE); return exchange.getResponse().setComplete(); } return chain.filter(exchange); }
@Override public int getOrder() { return 0; } }
|
启动:
![1597068959493]()
测试:
1 2
| 正确:http://localhost:9527/payment/lb?uname=z3 错误 http://localhost:9527/payment/lb
|