SpringBoot根据不同IP限制接口的QPS

根据对方IP地址来限制接口的QPS(每秒查询率),你可以结合Spring Boot应用、Guava的RateLimiter或者自定义的并发控制逻辑来实现。以下是一个基于Guava RateLimiter和Spring Boot的示例,展示如何根据IP地址来限制接口的QPS:

  1. 添加Guava依赖

首先,确保你的pom.xml文件中包含了Guava的依赖。

  1. 创建RateLimiter存储

你可以使用ConcurrentHashMap来存储每个IP地址对应的RateLimiter。

java 复制代码
import com.google.common.util.concurrent.RateLimiter;
import java.util.concurrent.ConcurrentHashMap;

public class IpRateLimiter {

    private final ConcurrentHashMap<String, RateLimiter> ipRateLimiterMap = new ConcurrentHashMap<>();

    private final double rate; // 例如:每秒允许的请求数

    public IpRateLimiter(double rate) {
        this.rate = rate;
    }

    public synchronized RateLimiter getRateLimiter(String ip) {
        return ipRateLimiterMap.computeIfAbsent(ip, k -> RateLimiter.create(rate));
    }
}
  1. 在Controller中使用RateLimiter

在Controller中,你可以从请求中获取IP地址,并使用IpRateLimiter来获取对应的RateLimiter,然后检查是否允许请求通过。

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

@RestController
public class MyController {

    @Autowired
    private IpRateLimiter ipRateLimiter;

    @GetMapping("/limited-endpoint")
    public String limitedEndpoint(HttpServletRequest request) {
        String ipAddress = request.getRemoteAddr(); // 简化的IP获取方式,可能需要根据实际情况调整
        RateLimiter rateLimiter = ipRateLimiter.getRateLimiter(ipAddress);

        if (!rateLimiter.tryAcquire()) {
            // 如果无法获取许可,则返回错误信息或执行其他逻辑
            return "Too Many Requests from IP: " + ipAddress + ", please try again later.";
        }

        // 如果可以获取许可,则处理请求并返回结果
        return "Success";
    }
}

注意 :上面的request.getRemoteAddr()方法可能只返回内网IP(如果请求经过反向代理),你可能需要配置X-Forwarded-For头来获取真实的客户端IP。

  1. 配置X-Forwarded-For

如果你的应用部署在反向代理(如Nginx)后面,你需要确保反向代理正确地设置了X-Forwarded-For头,并且你的Spring Boot应用能够解析这个头来获取真实的客户端IP。

  1. 清理RateLimiter

由于RateLimiter实例在ipRateLimiterMap中会一直存在,直到应用重启,你可能需要实现一种机制来清理长时间没有活动的RateLimiter实例,以避免内存泄漏。这可以通过定期扫描并移除长时间未使用的RateLimiter来实现。

  1. 其他考虑
  • 如果有大量不同的IP地址访问你的接口,ipRateLimiterMap可能会变得非常大。你可能需要考虑如何限制其大小或实现一种缓存淘汰策略。
  • 在生产环境中,你可能还需要考虑如何优雅地处理被限流的请求,例如返回特定的HTTP状态码、记录日志等。
相关推荐
计算机毕设定制辅导-无忧学长5 分钟前
《基于SpringBoot的庭院玫瑰栽培养护知识交互式科普平台设计与实现》
java·spring boot·后端·毕业设计·个性化推荐·协同过滤算法·庭院玫瑰栽培养护知识科普平台
骇客野人7 分钟前
SpringBoot数十Jar包批量生产部署落地实施方案(Shell+Systemd完整版)
spring boot·后端·jar
evans在进步17 分钟前
IP 网络基础详解:路由、ICMP、NAT、子网与 VLAN
网络·tcp/ip·php
Da Da 泓34 分钟前
UDP和TCP中的网络编程
网络·tcp/ip·udp·java-ee
Json____1 小时前
从零构建家政服务平台:一套全栈架构如何打通管理端与移动端-java-springboot
java·spring boot·后端·架构·毕设·wwwoop.com
leeyi1 小时前
命令行里的平台:df_cli 都会什么(第108篇)
后端·aigc·agent
ITxiaobing20231 小时前
技术选型参考:从IPinfo出发,聊聊IP情报服务的替代方案与选型逻辑
网络·网络协议·tcp/ip
云雀衔光1 小时前
Java Spring AI MCP:在 Spring 里把 AI 接上你的业务系统
java·开发语言·人工智能·后端·测试工具·spring
苏渡苇1 小时前
Spring Insight 里如何对 Span 进行清洗
java·spring boot·后端·spring·系统监控
WeiXin_DZbishe1 小时前
基于springboot大学生提问箱系统-计算机毕设【课程设计】72593
javascript·vue.js·spring boot·vscode·python·node.js·php