Ric*_*cky 18 java rest controller spring-mvc spring-boot
我正在开发一个Spring Boot Rest API来处理大量的传入请求调用.我的控制器如下所示:
@RestController
public class ApiController {
List<ApiObject> apiDataList;
@RequestMapping(value="/data",produces={MediaType.APPLICATION_JSON_VALUE},method=RequestMethod.GET)
public ResponseEntity<List<ApiObject>> getData(){
List<ApiObject> apiDataList=getApiData();
return new ResponseEntity<List<ApiObject>>(apiDataList,HttpStatus.OK);
}
@ResponseBody
@Async
public List<ApiObject> getApiData(){
List<ApiObject> apiDataList3=new List<ApiObject> ();
//do the processing
return apiDataList3;
}
}
Run Code Online (Sandbox Code Playgroud)
所以现在我想为每个用户设置一个ratelimit.假设每个用户每分钟只能请求5个请求或类似的东西.如何设置每个用户的速率限制,每分钟只能进行5次api呼叫,如果用户请求的次数超过了我可以发回429响应?我们需要他们的IP地址吗?
任何帮助表示赞赏.
Mau*_*ice 21
这是针对那些寻求限制每个用户(IP 地址)每秒请求数的人的解决方案。此解决方案需要 Google 的Guava library. 您将使用LoadingCache该类来存储请求计数和客户端 IP 地址。您还将需要javax.servlet-api依赖项,因为您将希望使用发生servlet filter请求计数的地方。代码如下:
import javax.servlet.Filter;
@Component
public class requestThrottleFilter implements Filter {
private int MAX_REQUESTS_PER_SECOND = 5; //or whatever you want it to be
private LoadingCache<String, Integer> requestCountsPerIpAddress;
public requestThrottleFilter(){
super();
requestCountsPerIpAddress = CacheBuilder.newBuilder().
expireAfterWrite(1, TimeUnit.SECONDS).build(new CacheLoader<String, Integer>() {
public Integer load(String key) {
return 0;
}
});
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
String clientIpAddress = getClientIP((HttpServletRequest) servletRequest);
if(isMaximumRequestsPerSecondExceeded(clientIpAddress)){
httpServletResponse.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
httpServletResponse.getWriter().write("Too many requests");
return;
}
filterChain.doFilter(servletRequest, servletResponse);
}
private boolean isMaximumRequestsPerSecondExceeded(String clientIpAddress){
int requests = 0;
try {
requests = requestCountsPerIpAddress.get(clientIpAddress);
if(requests > MAX_REQUESTS_PER_SECOND){
requestCountsPerIpAddress.put(clientIpAddress, requests);
return true;
}
} catch (ExecutionException e) {
requests = 0;
}
requests++;
requestCountsPerIpAddress.put(clientIpAddress, requests);
return false;
}
public String getClientIP(HttpServletRequest request) {
String xfHeader = request.getHeader("X-Forwarded-For");
if (xfHeader == null){
return request.getRemoteAddr();
}
return xfHeader.split(",")[0]; // voor als ie achter een proxy zit
}
@Override
public void destroy() {
}
}
Run Code Online (Sandbox Code Playgroud)
所以这基本上做的是它将所有请求制作 ip 地址存储在一个LoadingCache. 这就像一个特殊的映射,其中每个条目都有一个过期时间。在构造函数中,过期时间设置为 1 秒。这意味着在第一次请求时,一个 IP 地址加上它的请求计数只会在 LoadingCache 中存储一秒钟。它会在到期时自动从地图中删除。如果在那一秒内有更多请求来自 IP 地址,isMaximumRequestsPerSecondExceeded(String clientIpAddress)则将这些请求添加到总请求计数中,但在此之前检查是否已超过每秒最大请求量。如果是这种情况,它返回 true 并且过滤器返回一个错误响应,状态码为 429,代表请求过多。
这样,每个用户每秒只能发出一定数量的请求。
编辑:确保让 Spring 对保存过滤器的包进行组件扫描,否则过滤器将无法工作。此外,因为它是用@Component 注释的,所以过滤器默认适用于所有端点(/*)。
如果 spring 检测到您的过滤器,您应该在启动期间在日志中看到类似的内容。
o.s.b.w.servlet.FilterRegistrationBean : Mapping filter:'requestThrottleFilter' to: [/*]
Dan*_*edo 12
你在Spring中没有那个组件.
Spring没有开箱即用的限速功能。
有一个bucket4j-spring-boot-starter项目,该项目使用带有令牌桶算法的bucket4j库来限制对REST api的访问。您可以通过应用程序属性文件进行配置。有一个选项可以限制访问基于IP地址或用户名。
作为示例,简单设置可以在10秒内独立于用户最多允许5个请求:
bucket4j:
enabled: true
filters:
- cache-name: buckets
url: .*
rate-limits:
- bandwidths:
- capacity: 5
time: 10
unit: seconds
Run Code Online (Sandbox Code Playgroud)
如果您使用的是Netflix Zuul,则可以使用Spring Cloud Zuul RateLimit,它使用不同的存储选项:Consul,Redis,Spring Data和Bucket4j。
| 归档时间: |
|
| 查看次数: |
13077 次 |
| 最近记录: |