SpringBoot介面限流的常用方案

2025年09月10日20:23:05 科技 1837

摘要:本文主要介紹SpringBoot項目的介面限流方案,市面上常用有2種限流方案漏桶和令牌桶,大家常用的都是令牌桶,本文也只實現了令牌桶的方案。

漏桶和令牌桶說明

漏桶和令牌桶是最常用的兩種限流演算法,核心差異如下:

特性

漏桶限流(Leaky Bucket)

令牌桶限流(Token Bucket)

核心邏輯

固定速率處理請求(「漏水」),桶緩衝突發請求

固定速率生成令牌,請求需獲取令牌才能處理

輸出速率

嚴格固定(等於漏水速率)

允許突發(最大為桶容量 + 新生成的令牌數)

突發容忍度

不允許突發(超過桶容量的請求直接拒絕)

允許突發(桶中令牌足夠時,可一次性處理多個請求)

資源利用率

可能較低(即使系統空閑,也需按固定速率處理)

較高(系統空閑時可積累令牌,突發時快速處理)

典型場景

嚴格要求速率穩定(如網路流量整形)

允許一定突發(如 API 介面限流)

項目基礎配置

pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>Spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.Redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.48.0</version>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>33.4.8-jre</version>
        </dependency>
    </dependencies>

application.yml

spring:
  data:
    redis:
      host: redis
      port: 6379

啟動類

@SpringBootApplication
public class RateLimitApplication {

    public static void main(String[] args) {
        SpringApplication.run(RateLimitApplication.class, args);
    }
}

基於Redisson的令牌桶

分散式系統中,使用 Redisson 實現並發限流是一種常見且高效的方式

RateType限流鍵(key)的設計

  • OVERALL模式:限流鍵需全局唯一(如 global_api_limit),確保所有請求共享同一個桶。
  • PER_CLIENT模式:限流鍵需能唯一標識客戶端(如 user:${userId}、ip:${clientIp}),確保每個客戶端獨立使用自己的桶。
@Slf4j
@RestController
@RequestMapping(value = "redisson/rate-limit")
public class RedissonRateLimitController {

    @Autowired
    private RedissonClient redissonClient;

    @PostMapping("create-order")
    public Object createOrder(String info){
        RRateLimiter rateLimiter = getLimiter();
        boolean b = rateLimiter.tryAcquire();
        if(b) {
            log.info("允許訪問");
            return "SUCCESS";
        }
        log.warn("限流了");
        throw new RuntimeException("請求太火爆");
    }

    /**
     * 獲取限流器
     * @return
     */
    private RRateLimiter getLimiter() {
        RRateLimiter rateLimiter = redissonClient.getRateLimiter("create-order");
        rateLimiter.trySetRate(RateType.PER_CLIENT, 20, Duration.ofSeconds(5L));
        return rateLimiter;
    }

}

測試結果

我單線程請求了8S,請求成功40個

SpringBoot介面限流的常用方案 - 天天要聞

Guava的實現

Guava 的 RateLimiter是單機環境下基於令牌桶演算法的輕量級限流工具,適用於控制介面請求頻率、資源訪問速率或任務執行頻率等場景。以下是不同場景下的使用案例,包含基礎用法、高級特性及實際業務集成。

介面說明

  • RateLimiter.create(10.0):創建一個每秒生成 10 個令牌的限流器(即允許每秒 10 個請求)。
  • RateLimiter rateLimiter = RateLimiter.create(20.0, 5, TimeUnit.SECONDS): //創建預熱限流器:目標速率 20 個/秒,預熱時間 5 秒(從 2 個/秒逐步提升到 20 個/秒)
  • rateLimiter.acquire(1):阻塞等待獲取 1 個令牌(若當前無令牌,會等待直到新令牌生成)。返回值為等待時間(秒)
  • rateLimiter.tryAcquire(long permits, long timeout, TimeUnit unit):非阻塞獲取

具體代碼

@Slf4j
@RestController
@RequestMapping(value = "guava/rate-limit")
public class GuavaRateLimitController {

    private static final RateLimiter rateLimiter = RateLimiter.create(5);

    @PostMapping("create-order")
    public Object createOrder(String info){
        boolean b = rateLimiter.tryAcquire();
        if(b) {
            log.info("允許訪問");
            return "SUCCESS";
        }
        log.warn("限流了");
        throw new RuntimeException("請求太火爆");
    }


}

結果

8s內成功訪問45個請求

SpringBoot介面限流的常用方案 - 天天要聞

基於nginx的限流

Nginx 限流核心模塊:ngx_http_limit_req_module

Nginx 內置的 ngx_http_limit_req_module基於漏桶演算法實現限流,通過以下兩個核心指令控制:

  • limit_req_zone:定義限流的共享內存區和基礎速率。
  • limit_req:在具體 location或 server塊中應用限流規則。

(1)定義限流共享內存區(limit_req_zone)

在 Nginx 主配置文件(nginx.conf)的 http塊中,定義共享內存區存儲限流狀態:

http {
    # 定義限流共享內存區(名稱=one,大小=10MB,速率=10請求/秒)
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;

    # 其他全局配置...
    include       mime.types;
    default_type  application/octet-stream;
}
  • $binary_remote_addr:限流的鍵(基於客戶端 IP 地址)。
  • zone=one:10m:共享內存區名稱為 one,大小為 10MB(根據客戶端數量調整,10MB 約支持 16 萬 IP)。
  • rate=10r/s:基礎速率(每秒允許 10 個請求)。

(2)在 server或 location中應用限流規則

在需要限流的站點配置(如 server塊)中,使用 limit_req指令應用規則,並設置被限流時的響應:

server {
    listen       80;
    server_name  example.com;

    location /api/ {
        # 應用限流規則(使用上面定義的 zone=one)
        limit_req zone=one burst=20 nodelay;  # burst=突發容量,nodelay=不等待直接拒絕
        
        # 被限流時返回 429 狀態碼,並跳轉到自定義錯誤頁
        limit_req_status_code 429;
        error_page 429 /custom_limit_msg;

        # 正常請求的反向代理(示例)
        proxy_pass http://backend_server;
    }

    # 自定義限流消息體(返回 JSON)
    location = /custom_limit_msg {
        internal;  # 僅內部訪問,禁止外部直接請求
        add_header Content-Type application/JSON;
        return 429 '{"code": 429, "message": "請求過於頻繁,請稍後再試"}';
    }
}

關鍵參數說明

參數/指令

含義

limit_req_zone

定義限流的共享內存區、鍵(如 IP)和基礎速率(rate=10r/s表示每秒 10 個請求)。

burst

突發容量(允許短時間內超過基礎速率的請求數),例如 burst=20表示最多允許 20 個突發請求。

nodelay

若啟用,被限流的請求直接拒絕(不等待);若禁用(默認),請求會等待直到令牌可用。

limit_req_status_code

設置被限流時的 HTTP 狀態碼(如 429 Too Many Requests)。

error_page

自定義限流時的響應內容(如返回 JSON 消息體)。

高級限流場景

1. 按用戶 ID 限流

若需按用戶 ID 限流(如防止惡意用戶高頻請求),可將限流鍵改為用戶 ID(需前端傳遞 X-User-ID頭):

nginx
複製
http {
    # 限流鍵為 X-User-ID 頭的值(需確保頭存在)
    limit_req_zone $http_x_user_id zone=user_limit:10m rate=5r/s;

    server {
        location /api/user/ {
            # 校驗 X-User-ID 頭是否存在,不存在則拒絕
            if ($http_x_user_id = "") {
                return 400 "Missing X-User-ID header";
            }
            
            # 應用限流(鍵為用戶 ID)
            limit_req zone=user_limit burst=10 nodelay;
            limit_req_status_code 429;
            error_page 429 /custom_limit_msg;
            
            proxy_pass http://backend_server;
        }
    }
}

科技分類資訊推薦

引領科技豪華MPV新風尚 第二代騰勢D9西安車展亮相 - 天天要聞

引領科技豪華MPV新風尚 第二代騰勢D9西安車展亮相

兼具宜商氣度與家用溫情的科技豪華旗艦MPV,第二代騰勢D9迎來西安地區正式亮相。新車依託全球新能源MPV冠軍底蘊,以第二代刀片電池、雙閥雲輦-C、天神之眼5.0智駕等核心技術全面升級,兼顧商務體面與家庭舒適,為西北高端用戶帶來一站式全能出行解決方案。
採購禁入!科華數據材料造假被拒門外 - 天天要聞

採購禁入!科華數據材料造假被拒門外

本報(chinatimes.net.cn)記者胡雅文 北京報道這家趕上AI算力風口的公司,因投標材料造假,被相關採購方列入禁入名單兩年,其此前提出的複議申請也被正式駁回。相關採購平台近日發布公告,明確駁回科華數據股份有限公司(下稱「科華數據」,002335.SZ)此前提交的複議申請。早在一年前,科華數據已被認定在「信息通信樞紐...
快評樂道L80:15萬元級買大五座,這波值得沖? - 天天要聞

快評樂道L80:15萬元級買大五座,這波值得沖?

日前,樂道L80正式發布並開啟預售,其整車購買預售價為24.58萬元起,租電購買預售價則低至15.98萬元起。面對大型SUV市場「細分再細分」之競爭趨勢,這款樂道年度重磅新車都有哪些優勢?又能否成為「大五座SUV革新之作」?下面,圈哥就帶大家全方位感受。
成都直擊凱威德:純電全尺寸SUV的張揚與大氣 - 天天要聞

成都直擊凱威德:純電全尺寸SUV的張揚與大氣

4月22日,凱迪拉克以奧斯卡級盛典規格,將上海保利大劇院點亮為璀璨舞台,在品牌代言人倪妮與全場嘉賓的共同見證下,凱迪拉克全尺寸純電公路旗艦——凱威德耀然上市。新車共推出長續航四驅Pro、高性能四驅Ultra兩款配置,官方售價區間為46.88萬-50.88萬元。