在互联网飞速发展的今天,随着系统用户规模的不断扩大和分布式架构的广泛应用,API 接口的稳定性和性能成为系统设计中至关重要的因素。无论是应对突发的流量高峰,还是防止恶意爬虫的恶意请求,限流策略都已成为现代系统不可或缺的一部分。
为什么需要接口限流?
为了解决上述问题,我们可以在 API 接口上实施限流策略,使得系统能够在高并发环境下保持稳定,并且能够合理应对各类突发情况。在本文中,我们将探讨如何在 SpringBoot 3.3 中,通过简单的配置和代码实现 API 接口的限流。
运行效果:
图片
图片
若想获取项目完整代码以及其他文章的项目源码,且在代码编写时遇到问题需要咨询交流,欢迎加入下方的知识星球。
我们将从项目的结构开始,先了解一下本示例项目的文件布局。
rate-limiter/├── src/│ ├── main/│ │ ├── java/com/icoderoad/ratelimiter/│ │ │ ├── controller/│ │ │ │ └── RateLimiterController.java│ │ │ ├── config/│ │ │ │ └── RateLimiterConfig.java│ │ │ ├── properties/│ │ │ │ └── RateLimiterProperties.java│ │ │ └── application/│ │ │ └── SpringBootRateLimiterApplication.java│ │ ├── resources/│ │ │ ├── templates/│ │ │ │ └── index.html│ │ │ └── application.yml└── pom.xml
接下来,我们将逐步搭建项目,实现 API 接口限流功能。
在 pom.xml 中引入以下依赖:
<?xml versinotallow="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.3.3</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.icoderoad</groupId> <artifactId>ratelimiter</artifactId> <version>0.0.1-SNAPSHOT</version> <name>ratelimiter</name> <description>Demo project for Spring Boot</description> <properties> <java.version>17</java.version> <guava.version>31.1-jre</guava.version> </properties> <dependencies> <!-- Spring Boot Web Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Guava 用于限流 --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>${guava.version}</version> </dependency> <!-- Thymeleaf 模板引擎 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
在 src/main/resources/application.yml 中配置限流参数:
server: port: 8080rate-limiter: permits-per-second: 5 # 每秒许可数 warmup-period: 0 # 预热时间(秒) timeout: 0 # 获取许可的超时时间(秒)
参数说明:
在 src/main/java/com/icoderoad/ratelimiter/properties/RateLimiterProperties.java 中创建配置属性类,用于映射 application.yml 中的配置:
package com.icoderoad.ratelimiter.propertie;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import lombok.Data;@Data@Component@ConfigurationProperties(prefix = "rate-limiter")public class RateLimiterProperties { /** * 每秒许可数 */ private double permitsPerSecond; /** * 预热时间(秒) */ private long warmupPeriod; /** * 获取许可的超时时间(秒) */ private long timeout;}
说明:
在 src/main/java/com/icoderoad/ratelimiter/config/RateLimiterConfig.java 中创建限流器配置:
package com.icoderoad.ratelimiter.config;import java.util.concurrent.TimeUnit;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import com.google.common.util.concurrent.RateLimiter;import com.icoderoad.ratelimiter.propertie.RateLimiterProperties;@Configurationpublic class RateLimiterConfig { /** * 配置 RateLimiter Bean * * @param properties 注入的限流配置属性 * @return RateLimiter 实例 */ @Bean public RateLimiter rateLimiter(RateLimiterProperties properties) { if (properties.getWarmupPeriod() > 0) { // 创建带有预热期的 RateLimiter return RateLimiter.create( properties.getPermitsPerSecond(), properties.getWarmupPeriod(), TimeUnit.SECONDS ); } else { // 创建标准的 RateLimiter return RateLimiter.create(properties.getPermitsPerSecond()); } }}
说明:
在 src/main/java/com/icoderoad/ratelimiter/controller/RateLimiterController.java 中创建控制器,处理 API 请求:
package com.icoderoad.ratelimiter.controller;import java.util.concurrent.TimeUnit;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.ResponseBody;import com.google.common.util.concurrent.RateLimiter;import com.icoderoad.ratelimiter.propertie.RateLimiterProperties;@Controllerpublic class RateLimiterController { @Autowired private RateLimiter rateLimiter; @Autowired private RateLimiterProperties properties; /** * 测试限流接口 * * @return 请求结果 */ @GetMapping("/api/test") @ResponseBody public ResponseEntity<String> testApi() { boolean acquired = rateLimiter.tryAcquire(properties.getTimeout(), TimeUnit.SECONDS); if (acquired) { // 允许请求,返回成功响应 return ResponseEntity.ok("请求成功!"); } else { // 拒绝请求,返回限流响应 return ResponseEntity.status(429).body("请求过多,请稍后再试!"); } }}
说明:
成功获取:返回 200 状态码和成功消息。
获取失败:返回 429 状态码和错误提示。
在 src/main/resources/templates/index.html 中创建前端页面,使用 Thymeleaf、Bootstrap 和 jQuery 实现:
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"> <title>API 限流测试</title> <!-- 引入 Bootstrap CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"> <!-- 自定义样式 --> <style> body { padding-top: 50px; } </style></head><body><div class="container"> <h1 class="mb-4">API 限流测试</h1> <button id="testButton" class="btn btn-primary">发送请求</button> <div id="alertPlaceholder" class="mt-3"></div></div><!-- 引入 jQuery --><script src="https://code.jquery.com/jquery-3.6.0.min.js"></script><!-- 引入 Bootstrap JS --><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script><script> $(document).ready(function () { $('#testButton').click(function () { $.ajax({ url: '/api/test', method: 'GET', success: function (response) { showAlert(response, 'success'); }, error: function (xhr) { if (xhr.status === 429) { showAlert(xhr.responseText, 'danger'); } else { showAlert('发生未知错误,请稍后重试。', 'warning'); } } }); }); /** * 显示提示信息 * @param message 消息内容 * @param type 提示类型('success', 'danger', 'warning' 等) */ function showAlert(message, type) { const alertHtml = ` <div class="alert alert-${type} alert-dismissible fade show" role="alert"> ${message} <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> </div> `; $('#alertPlaceholder').html(alertHtml); } });</script></body></html>
说明:
使用 CDN 加载 Bootstrap 和 jQuery,确保资源的快速和稳定加载。
一个按钮用于触发 API 请求。
一个占位符 div 用于显示提示信息。
JavaScript 逻辑:
使用 jQuery 监听按钮点击事件,发送 AJAX 请求到 /api/test 接口。
根据响应结果,调用 showAlert 函数,在页面上显示不同类型的提示信息。
showAlert 函数使用 Bootstrap 的 Alert 组件,提供友好的用户提示。
效果展示:
在 src/main/java/com/icoderoad/ratelimiter/application/SpringBootRateLimiterApplication.java 中启动 Spring Boot 应用:
package com.icoderoad.ratelimiter;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication(scanBasePackages = "com.icoderoad.ratelimiter")public class RatelimiterApplication { public static void main(String[] args) { SpringApplication.run(RatelimiterApplication.class, args); }}
说明:
步骤:
示例演示:
通过本文的示例,我们成功地在 Spring Boot 3.3 中实现了简单而有效的 API 接口限流功能。我们利用了 Guava 提供的 RateLimiter 工具,结合 Spring Boot 的配置属性管理和依赖注入机制,实现了灵活可配的限流策略。同时,通过前端页面的简单设计和友好提示,使得用户能够清晰地感知到限流机制的存在和作用。
本文链接:http://www.28at.com/showinfo-26-112716-0.htmlSpringBoot 3.3 中实现 API 接口限流就是这么简单
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com