【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.pswp.cn/pingmian/81494.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81494.shtml
英文地址,請注明出處:http://en.pswp.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 確保你…