【Java-EE进阶】SpringBoot针对某个IP限流问题

目录

简介

1. 使用Guava的RateLimiter实现限流

添加Guava依赖

实现RateLimiter限流逻辑

限流管理类

控制器中应用限流逻辑

2. 使用计数器实现限流

限流管理类

控制器中应用限流逻辑


简介

针对某个IP进行限流以防止恶意点击是一种常见的反爬虫和防止DoS的措施。限流策略通过对某个IP的访问频率进行控制,防止恶意用户对应用造成负面的影响。

以下是实现限流的步骤和方法,在Java后端通常这样实现:

1. 使用Guava的RateLimiter实现限流

Guava库提供了一个简单而高效的限流工具:RateLimiter,可以方便的实现针对IP的访问频率控制。

添加Guava依赖

首先,在pom.xml文件中添加Guava依赖:

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.1-jre</version>
</dependency>
实现RateLimiter限流逻辑
限流管理类

创建一个类来管理针对IP的限流:

import com.google.common.util.concurrent.RateLimiter;import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;public class RateLimiterManager {private final ConcurrentMap<String, RateLimiter> rateLimiterMap = new ConcurrentHashMap<>();private final double permitsPerSecond = 1.0; // 每秒允许1次请求public boolean tryAcquire(String ip) {RateLimiter rateLimiter = rateLimiterMap.computeIfAbsent(ip, k -> RateLimiter.create(permitsPerSecond));return rateLimiter.tryAcquire();}
}
控制器中应用限流逻辑

在Spring Boot控制器中应用限流逻辑:

import com.xfusion.rate1.limit.RateLimiterManager;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;@RestController
@RequestMapping("/test")
public class TestController {private final RateLimiterManager rateLimiterManager=new RateLimiterManager();@RequestMapping("/t1")public void test1(HttpServletRequest request, HttpServletResponse response) throws IOException {String param=request.getRemoteAddr();if(rateLimiterManager.tryAcquire(param)) {response.getWriter().write("Request processed for " + param);} else {response.setStatus(HttpServletResponse.SC_FORBIDDEN);response.getWriter().write("Request limit for " + param);}}
}
private final ConcurrentMap<String, RateLimiter> rateLimiterMap = new ConcurrentHashMap<>();
  • ConcurrentMap<String, RateLimiter>

    • 使用ConcurrentMap来存储每个IP的限流器(RateLimiter)。
    • ConcurrentMap接口允许高效地进行并发访问和更新,确保线程安全。
  • new ConcurrentHashMap<>()

    • 实例化一个ConcurrentHashMap,它是ConcurrentMap的常用实现。这种数据结构支持线程安全的读写操作,适合限流场景。
private final double permitsPerSecond = 1.0; // 每秒允许1次请求
  • permitsPerSecond
    • 定义一个double类型的常量permitsPerSecond,值为1.0
    • 表示每秒允许1次请求的限流速率。RateLimiter根据此值来创建相应的限流器。
RateLimiter rateLimiter = rateLimiterMap.computeIfAbsent(ip, k -> RateLimiter.create(permitsPerSecond));
  • computeIfAbsent

    • computeIfAbsent方法用于检查map中是否已经存在为该IP准备的RateLimiter
    • 若不存在,则使用k -> RateLimiter.create(permitsPerSecond)创建一个新的RateLimiter。这个lambda部分表示为未存在的IP创建一个新的RateLimiter,限流速率为permitsPerSecond
  • RateLimiter.create(permitsPerSecond)

    • 调用RateLimiter类的静态方法create,以指定速率创建一个新的限流器实例。这使得每秒最多处理一个请求。
return rateLimiter.tryAcquire();
  • rateLimiter.tryAcquire()
    • 尝试获取一个请求许可。在给定的限流速率范围内,如果成功获取许可,则返回true,否则返回false
    • tryAcquire使得在请求达到速率限制时,予以限制,而不使请求排队。
response.setStatus(HttpServletResponse.SC_FORBIDDEN);

如果我们发现请求达到了上限的时候,设置相应的状态码,然后前端会根据相应的状态码来完成请求,同时就防止这个ip然后再进行访问。

2. 使用计数器实现限流

计数器限流比较简单,通过记录每个IP的请求次数并在指定时间窗口内进行限流。

限流管理类

创建一个类来管理限流逻辑:

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
@Configuration
@Component
public class CounterRateLimiter {private final ConcurrentHashMap<String, AtomicInteger> requestCounts = new ConcurrentHashMap<>();private final int maxRequestsPerMinute = 10;public boolean tryAcquire(String ipAddress) {AtomicInteger requestCount = requestCounts.computeIfAbsent(ipAddress, k -> new AtomicInteger(0));int currentCount = requestCount.incrementAndGet();log.info("IP: " + ipAddress + ", Current Count: " + currentCount);return currentCount <= maxRequestsPerMinute;}public void resetCounts() {log.info("Reset counts");requestCounts.clear();}@Scheduled(fixedRate = 10000)public void resetCountsScheduled() {log.info("刷新这个ip的次数");resetCounts();}
}

在开启定时任务的时候,要在Application上添加上@EnableScheduling这个注解

@SpringBootApplication
@Configuration
@EnableScheduling
public class Rate1Application {public static void main(String[] args) {SpringApplication.run(Rate1Application.class, args);}}
控制器中应用限流逻辑

在Spring Boot控制器中应用限流逻辑,并定期重置计数器:

private final CounterRateLimiter counterRateLimiter;public TestController(CounterRateLimiter counterRateLimiter) {this.counterRateLimiter = counterRateLimiter;}@RequestMapping("/t2")public void test2(HttpServletRequest request, HttpServletResponse response) throws IOException {String param = request.getRequestURI();if (counterRateLimiter.tryAcquire(param)) {log.info("打印日志1");response.getWriter().write("Request processed for test2 " + param);} else {log.info("打印日志2");response.setStatus(HttpServletResponse.SC_FORBIDDEN);response.getWriter().write("Request limit for test2" + param);}}
@Scheduled(fixedRate = 10000)
public void resetCountsScheduled() {log.info("刷新这个ip的次数");resetCounts();
}
  • @Scheduled(fixedRate = 10000):注解用于配置定时任务,每10秒执行一次。
    • fixedRate:设定定时任务的执行频率,这里设置为每10000毫秒(即每10秒)。
  • resetCountsScheduled 方法:定时任务调用 resetCounts 方法清空计数器。
    • 日志记录:记录定时任务执行。
    • 调用 resetCounts:每10秒自动调用 resetCounts 方法重置计数器。
public void resetCounts() {log.info("Reset counts");requestCounts.clear();
}

resetCounts:用于重置计数器。

  • 日志记录:记录重置计数器操作。
  • clear:清空 requestCounts 中的所有键值对,重置所有IP的计数器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/81494.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux问题排查-找到偷偷写文件的进程

在 Linux 系统中&#xff0c;若要通过已修改的文件找到修改该文件的进程 PID&#xff0c;可以结合以下方法分析&#xff0c;具体取决于文件是否仍被进程打开或已被删除但句柄仍存在&#xff1a; 一、文件仍被进程打开&#xff08;未删除&#xff09; 如果文件当前正在被某个进…

More Effective C++:改善编程与设计(下)

目录 条款19:了解临时对象的来源 条款20:协助完成“返回值优化” 条款21:利用重载技术避免隐式类型转换 条款22:考虑以操作符复合形式&#xff08;op&#xff09;取代其独身形式&#xff08;op&#xff09; 条款23:考虑使用其他程序库 条款24:了解virtual functions、mul…

VTK|类似CloudCompare的比例尺实现2-vtk实现

文章目录 实现类头文件实现类源文件调用逻辑关键问题缩放限制问题投影模式项目git链接实现类头文件 以下是对你提供的 ScaleBarController.h 头文件添加详细注释后的版本,帮助你更清晰地理解每个成员和方法的用途,尤其是在 VTK 中的作用: #ifndef SCALEBARCONTROLLER_H #de…

PostgreSQL 联合索引生效条件

最近面试的时候&#xff0c;总会遇到一个问题 在 PostgreSQL 中&#xff0c;联合索引在什么条件下会生效&#xff1f; 特此记录~ 前置信息 数据库版本 PostgreSQL 14.13, compiled by Visual C build 1941, 64-bit 建表语句 CREATE TABLE people (id SERIAL PRIMARY KEY,c…

SpringBoot项目里面发起http请求的几种方法

在Spring Boot项目中发起HTTP请求的方法 在Spring Boot项目中&#xff0c;有几种常用的方式可以发起HTTP请求&#xff0c;以下是主要的几种方法&#xff1a; 1. 使用RestTemplate (Spring 5之前的主流方式) // 需要先注入RestTemplate Autowired private RestTemplate restT…

《Python星球日记》 第90天:微调的概念以及如何微调大模型?

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、微调原理1. 什么是大模型微调?2. 为什么需要微调?3. 微调的基本流程4. 微调策略分类二、LoRA(Low-Rank Adaptation)技术详解1. LoRA的核…

机器学习-人与机器生数据的区分模型测试 - 模型融合与检验

模型融合 # 先用普通Pipeline训练 from sklearn.pipeline import Pipeline#from sklearn2pmml.pipeline import PMMLPipeline train_pipe Pipeline([(scaler, StandardScaler()),(ensemble, VotingClassifier(estimators[(rf, RandomForestClassifier(n_estimators200, max_de…

怎样免费开发部署自己的网站?

要免费开发自己的网站&#xff0c;您可以根据自己的技术水平和需求选择以下两种主要方式&#xff1a; 零基础用户&#xff1a;建议使用如WordPress.com、Weebly、Strikingly等平台&#xff0c;快速搭建网站。 有一定技术基础的用户&#xff1a;可选择自行开发网站&#xff0c;…

调用百度云API机器翻译

新建Python文件&#xff0c;叫 text_translator.py 输入 import requests import jsonAPI_KEY "glYiYVF2dSc7EQ8n78VDRCpa" # 替换为自己的API Key SECRET_KEY "kUlhze8OQZ7xbVRp" # 替换为自己的Secret Keydef main():# 选择翻译方向while True:di…

OpenAI与微软洽谈新融资及IPO,Instagram因TikTok流失四成用户

OpenAI与微软洽谈新融资及IPO 据悉&#xff0c;OpenAI 正与微软洽谈新融资及筹备 IPO&#xff0c;关键问题是微软在 OpenAI 重组后的股权比例。微软已投资超 130 亿美元&#xff0c;双方修订 2019 年合同&#xff0c;微软拟弃部分股权换新技术访问权。OpenAI 上周放弃了有争议转…

git工具使用详细教程-------命令行和TortoiseGit图形化

下载 git下载地址&#xff1a;https://git-scm.com/downloads TortoiseGit&#xff08;图形化工具&#xff09;下载地址&#xff1a;https://tortoisegit.org/download/ 认识git结构 工作区&#xff1a;存放代码的地方 暂存区&#xff1a;临时存储&#xff0c;将工作区的代码…

构建RAG混合开发---PythonAI+JavaEE+Vue.js前端的实践

7GB显存如何部署bf16精度的DeepSeek-R1 70B大模型&#xff1f;-CSDN博客 服务容错治理框架resilience4j&sentinel基础应用---微服务的限流/熔断/降级解决方案-CSDN博客 conda管理python环境-CSDN博客 快速搭建对象存储服务 - Minio&#xff0c;并解决临时地址暴露ip、短…

【Java ee初阶】jvm(3)

一、双亲委派机制&#xff08;类加载机制中&#xff0c;最经常考到的问题&#xff09; 类加载的第一个环节中&#xff0c;根据类的全限定类名&#xff08;包名类名&#xff09;找到对应的.class文件的过程。 JVM中进行类加载的操作&#xff0c;需要以来内部的模块“类加载器”…

wps excel将表格输出pdf时所有列在一张纸上

记录&#xff1a;wps excel将表格输出pdf时所有列在一张纸上 1&#xff0c;调整缩放比例&#xff0c;或选择将所有列打印在一页 2&#xff0c;将表格的所有铺满到这套虚线

分布式微服务系统架构第134集:笔记1运维服务器经验,高并发,大数据量系统

加群联系作者vx&#xff1a;xiaoda0423 仓库地址&#xff1a;https://webvueblog.github.io/JavaPlusDoc/ https://1024bat.cn/ https://github.com/webVueBlog/fastapi_plus https://webvueblog.github.io/JavaPlusDoc/ ✅ 一、查看端口是否被占用的常用命令 1️⃣ lsof 命令&…

IS-IS 中间系统到中间系统

前言&#xff1a; 中间系统到中间系统IS-IS&#xff08;Intermediate System to Intermediate System&#xff09;属于内部网关协议IGP&#xff08;Interior Gateway Protocol&#xff09;&#xff0c;用于自治系统内部 IS-IS也是一种链路状态协议&#xff0c;使用最短路径优先…

前端安全:XSS、CSRF 防御与最佳实践

引言 随着互联网应用的普及&#xff0c;前端安全问题日益凸显。作为开发者&#xff0c;了解并防范常见的安全威胁至关重要。本文将深入探讨两种最常见的前端安全威胁&#xff1a;跨站脚本攻击&#xff08;XSS&#xff09;和跨站请求伪造&#xff08;CSRF&#xff09;&#xff…

uniapp 弹窗封装(上、下、左、右、中五个方位)

无脑复制即可&#xff01;&#xff01;&#xff01; <template><view><viewv-if"mask"class"tui-drawer-mask":class"{ tui-drawer-mask_show: visible }":style"{ zIndex: maskZIndex }"tap"handleMaskClick&qu…

Axure制作可视化大屏动态滚动列表教程

在可视化大屏设计中&#xff0c;动态滚动列表是一种常见且实用的展示方式&#xff0c;能够有效地展示大量信息。本文将详细介绍如何使用Axure制作一个动态滚动的列表展示模块。 一、准备工作 打开Axure软件&#xff1a;确保你已经安装并打开了Axure RP软件。创建新项目&#x…

零基础玩转Apache Superset可视化部署

根据官方Quick Start Guide&#xff0c;你可以按照以下步骤进行部署&#xff1a; 1. 确认环境2. 获取代码3. 获取官方最新代码4. 启动服务5. 访问Superset Web界面6. 接入数据源 前提条件&#xff1a; dockerdocker compose 1. 确认环境 安装Docker和Docker Compose 确保你…