Commit 955e418e authored by 朱允伟's avatar 朱允伟

<dev> 添加网关并对接口执行进行限流控制

parent e8e68a14
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>api-service</artifactId>
<groupId>com.zorkdata</groupId>
<version>4.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>api-service-gateway</artifactId>
<packaging>jar</packaging>
<dependencies>
<!--gateway 网关依赖,内置webflux 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.vladimir-bukhtoyarov/bucket4j-core -->
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-core</artifactId>
<version>6.2.0</version>
</dependency>
<!--注册中心客户端-->
<!-- <dependency>-->
<!-- <groupId>com.alibaba.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>-->
<!-- </dependency>-->
<!-- &lt;!&ndash;配置中心客户端&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.alibaba.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>-->
<!-- </dependency>-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.zorkdata.apiservice.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.context.ApplicationContext;
import java.util.Map;
/**
* @author zyw
* @create 2021-10-08-14:54
*/
@SpringCloudApplication
public class ApiServiceGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiServiceGatewayApplication.class,args);
}
}
package com.zorkdata.apiservice.gateway.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author zyw
* @create 2021-10-08-17:57
*/
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("api-router", r->r.path("/apiservice/**")
.uri("http://localhost:9086")).build();
return routes.build();
}
@Bean
public RestTemplate restTemplate()
{
return new RestTemplate();
}
}
package com.zorkdata.apiservice.gateway.filter;
import com.zorkdata.apiservice.gateway.schedule.ApiLimitCache;
import io.github.bucket4j.Bucket;
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.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @author zyw
* @create 2021-10-08-18:37
*/
@Component
public class GatewayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String apiName = exchange.getRequest().getQueryParams().getFirst("apiName");
if(null == apiName){
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
return exchange.getResponse().setComplete();
}
Bucket bucket = ApiLimitCache.BUCKET_CACHE.get(apiName);
if(null == bucket){
return chain.filter(exchange);
}else {
if (bucket.tryConsume(1))
{
return chain.filter(exchange);
}
else
{
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
return exchange.getResponse().setComplete();
}
}
}
@Override
public int getOrder() {
return 0;
}
}
package com.zorkdata.apiservice.gateway.schedule;
import io.github.bucket4j.Bucket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author zyw
* @create 2021-10-09-13:34
*/
public class ApiLimitCache {
public static final Map<String, Bucket> BUCKET_CACHE = new ConcurrentHashMap<>(500);
}
package com.zorkdata.apiservice.gateway.schedule;
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket4j;
import io.github.bucket4j.Refill;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import javax.annotation.PostConstruct;
import java.time.Duration;
/**
* @author zyw
* @create 2021-10-09-13:38
*/
@Component
@EnableScheduling
@Slf4j
public class RefreshApiLimitSchedule {
@Autowired
private RestTemplate restTemplate;
/**
* 添加定时任务
* 每小时执行一次
*/
@Scheduled(cron = "0 0 0/1 * * ?")
@PostConstruct
private void refreshTask() {
String url = "http://";
int capacity = 2000;//桶的最大容量,即能装载 Token 的最大数量
int refillTokens = 2000; //每次 Token 补充量
Duration duration = Duration.ofSeconds(1); //补充 Token 的时间间隔
Refill refill = Refill.greedy(refillTokens, duration);
Bandwidth limit = Bandwidth.classic(capacity, refill);
ApiLimitCache.BUCKET_CACHE.put("api",Bucket4j.builder().addLimit(limit).build());
}
}
server:
port: 10001
spring:
application:
name: @artifactId@
# cloud:
# gateway:
# routes:
# - id: api-service
# uri: http://localhost:9086
# predicates:
# - Path=/apiservice/**
...@@ -128,5 +128,6 @@ ...@@ -128,5 +128,6 @@
<modules> <module>api-service-common</module> <modules> <module>api-service-common</module>
<module>api-service-project</module> <module>api-service-project</module>
</modules> <module>api-service-gateway</module>
</modules>
</project> </project>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment