限流10萬QPS、跨域、過濾器、令牌桶算法-網關Gateway內容柒哥都給你總結在這兒了
閱讀本文大概需要 7 分鐘。
一、微服務網關Spring Cloud Gateway
1.1 導引
1.2 什么是微服務網關Gateway?
This project provides a library for building an API Gateway on top of Spring WebFlux.
https://spring.io/projects/spring-cloud-gateway
nginx ?Nginx (engine x) 是一個高性能的HTTP和反向代理web服務器,同時也提供了IMAP/POP3/SMTP服務
zuul ,Zuul 是 Netflix 出品的一個基于 JVM 路由和服務端的負載均衡器。
spring-cloud-gateway, 是spring 出品的 基于spring 的網關項目,集成斷路器,路徑重寫,性能比Zuul好。
1.3 微服務為什么要使用網關呢?
客戶端會多次請求不同的微服務,增加了客戶端的復雜性
存在跨域請求,在一定場景下處理相對復雜
認證復雜,每個服務都需要獨立認證
難以重構,隨著項目的迭代,可能需要重新劃分微服務。例如,可能將多個服務合并成一個或者將一個服務拆分成多個。如果客戶端直接與微服務通信,那么重構將會很難實施
某些微服務可能使用了防火墻 / 瀏覽器不友好的協(xié)議,直接訪問會有一定的困難

1.4 微服務網關優(yōu)點
安全 ,只有網關系統(tǒng)對外進行暴露,微服務可以隱藏在內網,通過防火墻保護。
易于監(jiān)控??梢栽诰W關收集監(jiān)控數據并將其推送到外部系統(tǒng)進行分析。
易于認證??梢栽诰W關上進行認證,然后再將請求轉發(fā)到后端的微服務,而無須在每個微服務中進行認證。
減少了客戶端與各個微服務之間的交互次數
易于統(tǒng)一授權。
1.5 總結
二、微服務網關搭建及配置
2.1 微服務網關微服務搭建

<dependency>
????<groupId>org.springframework.cloudgroupId>
????<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
<dependency>
????<groupId>org.springframework.cloudgroupId>
????<artifactId>spring-cloud-starter-netflix-hystrixartifactId>
dependency>
<dependency>
????<groupId>org.springframework.cloudgroupId>
????<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
@SpringBootApplication
@EnableEurekaClient
public?class?GatewayApplication?{
????public?static?void?main(String[]?args)?{
????????SpringApplication.run(GatewayApplication.class,?args);
????}
}
spring:
??application:
????name:?apigateway
??cloud:
????gateway:
??????routes:
??????-?id:?open
????????uri:?lb://open
????????predicates:
????????-?Path=/open/**
????????filters:
????????-?StripPrefix=?1
??????-?id:?system
????????uri:?lb://system
????????predicates:
????????-?Path=/system/**
????????filters:
????????-?StripPrefix=?1
server:
??port:?9999
eureka:
??client:
????service-url:
??????defaultZone:?http://127.0.0.1:10086/eureka
??instance:
????prefer-ip-address:?true
https://cloud.spring.io/spring-cloud-gateway/spring-cloud-gateway.html#_stripprefix_gatewayfilter_factory
2.2 微服務網關跨域
@Bean
public?CorsWebFilter?corsFilter()?{
????CorsConfiguration?config?=?new?CorsConfiguration();
????config.addAllowedMethod("*");//支持所有方法
????config.addAllowedOrigin("*");//跨域處理?允許所有的域
????config.addAllowedHeader("*");//支持所有請求頭
????UrlBasedCorsConfigurationSource?source?=?new?UrlBasedCorsConfigurationSource(new?PathPatternParser());
????source.registerCorsConfiguration("/**",?config);//匹配所有請求
????return?new?CorsWebFilter(source);
}
三、微服務網關過濾器
@Component
public?class?IpFilter?implements?GlobalFilter,?Ordered?{
????@Override
????public?Mono?filter(ServerWebExchange?exchange,?GatewayFilterChain?chain)? {
????????ServerHttpRequest?request?=?exchange.getRequest();
????????InetSocketAddress?remoteAddress?=?request.getRemoteAddress();
????????//TODO?設置ip白名單
????????System.out.println("ip:"+remoteAddress.getHostName());
????????return?chain.filter(exchange);
????}
????@Override
????public?int?getOrder()?{
????????return?1;
????}
}
@Component
public?class?UrlFilter?implements?GlobalFilter,?Ordered?{
????@Override
????public?Mono?filter(ServerWebExchange?exchange,?GatewayFilterChain?chain)? {
????????ServerHttpRequest?request?=?exchange.getRequest();
????????String?url?=?request.getURI().getPath();
????????//TODO?攔截特定URL地址
????????System.out.println("url:"+url);
????????return?chain.filter(exchange);
????}
????@Override
????public?int?getOrder()?{
????????return?2;
????}
}
四、網關限流每秒10萬請求
4.1 限流實現思路分析

4.2 令牌桶算法 介紹

4.3 網關限流代碼實現
(1)spring cloud gateway 默認使用redis的RateLimter限流算法來實現。所以我們要使用首先需要引入redis的依賴
<dependency>
????<groupId>org.springframework.bootgroupId>
????<artifactId>spring-boot-starter-data-redis-reactiveartifactId>
????<version>2.1.3.RELEASEversion>
dependency>
(2)定義KeyResolver
????//定義一個KeyResolver
????@Bean
????public?KeyResolver?ipKeyResolver()?{
????????return?new?KeyResolver()?{
????????????@Override
????????????public?Mono?resolve(ServerWebExchange?exchange)? {
????????????????return?Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
????????????}
????????};
????}
(3)修改application.yml中配置項,指定限制流量的配置以及REDIS的配置,修改后最終配置如下:
spring:
??application:
????name:?apigateway
??cloud:
????gateway:
??????routes:
??????-?id:?open
????????uri:?lb://open
????????predicates:
????????-?Path=/open/**
????????filters:
????????-?StripPrefix=?1
????????-?name:?RequestRateLimiter?#請求數限流?名字不能隨便寫?
??????????args:
????????????key-resolver:?"#{@ipKeyResolver}"
????????????redis-rate-limiter.replenishRate:?1
????????????redis-rate-limiter.burstCapacity:?1
??????-?id:?system
????????uri:?lb://system
????????predicates:
????????-?Path=/system/**
????????filters:
????????-?StripPrefix=?1
??#?配置Redis?127.0.0.1可以省略配置
??redis:
????host:?101.57.2.128
????port:?6379
server:
??port:?9999
eureka:
??client:
????service-url:
??????defaultZone:?http://127.0.0.1:100/eureka
??instance:
????prefer-ip-address:?true
burstCapacity:令牌桶總容量。
replenishRate:令牌桶每秒填充平均速率。
key-resolver:用于限流的鍵的解析器的 Bean 對象的名字。它使用 SpEL 表達式根據#{@beanName}從 Spring 容器中獲取 Bean 對象。
replenishRate和中設置相同的值來實現穩(wěn)定的速率burstCapacity。設置burstCapacity高于時,可以允許臨時突發(fā)replenishRate。在這種情況下,需要在突發(fā)之間允許速率限制器一段時間(根據replenishRate),因為2次連續(xù)突發(fā)將導致請求被丟棄(HTTP 429 - Too Many Requests)(4)測試時需要注意服務啟動順序,這里需要依賴于Redis,所以首先要啟動redis
啟動redis
啟動注冊中心
啟動商品微服務
啟動gateway網關
打開瀏覽器 ?http://localhost:9999/open
快速刷新,當1秒內發(fā)送超過10萬次請求,就會返回429錯誤。
推薦閱讀:
微信掃描二維碼,關注我的公眾號
朕已閱?

