Java 使用 Google Guava 实现接口限流

一、引入依赖

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

二、自定义注解及限流拦截器

自定义注解:@Limiter

package com.haitai.web.device.annotation;import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;/*** 限流注解** @Author xincheng.du* @Date 2023/7/5 17:13*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Limiter {/*** 每秒创建令牌个数,默认:0.5* 代表每秒允许通过的请求数为0.5个,即2秒只能通过一个请求*/double qps() default 0.5D;/*** 获取令牌等待超时时间 默认:500*/long timeout() default 500;/*** 超时时间单位 默认:毫秒*/TimeUnit timeunit() default TimeUnit.MILLISECONDS;/*** 限速提示信息*/String msg() default "访问过于频繁,请稍候再试";
}

限流拦截器:RequestLimitingInterceptor

package com.haitai.web.device.interceptor;import com.google.common.util.concurrent.RateLimiter;
import com.haitai.web.device.annotation.Limiter;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** 限流拦截器** @Author xincheng.du* @Date 2023/7/5 15:38*/
@Component
@Slf4j
public class RequestLimitingInterceptor implements HandlerInterceptor {private final Map<String, RateLimiter> rateLimiterMap = new ConcurrentHashMap<>();@Overridepublic boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;Limiter rateLimit = handlerMethod.getMethodAnnotation(Limiter.class);// 判断是否有注解if (rateLimit != null) {// 获取请求urlString url = request.getRequestURI();// 判断map集合中是否有创建好的令牌桶rateLimiterMap.put(url, rateLimiterMap.computeIfAbsent(url, key -> RateLimiter.create(rateLimit.qps())));RateLimiter rateLimiter = rateLimiterMap.get(url);// 获取令牌boolean acquire = rateLimiter.tryAcquire(rateLimit.timeout(), rateLimit.timeunit());if (!acquire) {log.warn("请求被限流,url:{}", request.getServletPath());throw new RuntimeException(rateLimit.msg());}}}return true;}}

三、测试

package com.haitai.web.controller.device;import com.haitai.common.annotation.Anonymous;
import com.haitai.web.device.annotation.Limiter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @Author xincheng.du* @Date 2023/7/24 10:04*/
@RestController
@RequestMapping("/test")
public class LimiterTestController {@Anonymous // 允许匿名访问@Limiter(qps = 0.2D) // 5秒一次@GetMapping("/limiter")public void limiter() {System.out.println("=============正常请求=============");}}

5秒内第一次请求:
在这里插入图片描述
5秒内第二次请求:
在这里插入图片描述

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

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

相关文章

安装requests模块及其他依赖库的完美解决办法

业务场景 导入requests库时报错&#xff0c;单独离线下载安装requests&#xff0c;发现仍然报错&#xff0c;问题在于requests库有其他依赖库。 WARNING: Retrying (Retry(total1, connectNone, readNone, redirectNone, statusNone)) after connection broken by NewConnect…

PgSQL-使用技巧-如何衡量网络对性能的影响

PgSQL-使用技巧-如何衡量网络对性能的影响 PG数据库和应用之间常见的部件有连接池、负载平衡组件、路由、防火墙等。我们常常不在意或者认为涉及的网络hops对整体性能产生的额外开销是理所当然的。但在很多情况下&#xff0c;它可能会导致严重的性能损失和拖累整体吞吐量。相当…

vue 图片的引入方式

一、import 静态引入 放在script标签顶端 例如 import errowPng from ../../assets/404_images/404.png 二、require 动态引入 可以放在data中 data() {return {imgUrl:require("../../assets/404_images/404.png")};}, require 是赋值过程并且是运行时才执行&…

普通的计算机专业大学生如何学习才能找到好offer

2023年已经将近8月份了&#xff0c;回想到开始努力提高自己的时候还是在今年1月1号。开学就要大二了。 一、目标达成情况总结&#xff1a; 一月份&#xff0c;无意间在网上刷到鹏哥的C语言课程&#xff0c;在鸡汤实力课程已拿到大厂offer的同学喜报 &#xff0c;让我萌发了学技…

深入浅出理解vue2/vue3响应式原理

一、简介 当谈论Vue 2和Vue 3的响应式原理时&#xff0c;我们主要关注的是其数据双向绑定的机制。数据双向绑定是指当数据发生变化时&#xff0c;视图会自动更新&#xff1b;反之&#xff0c;当视图发生变化时&#xff0c;数据也会相应地更新。这种特性让我们在前端开发中更加…

Swift 如何确定 scrollView 已经滑动结束

在 iOS 的 UIScrollView 中&#xff0c;你可以通过实现 UIScrollViewDelegate 的方法来检测滑动结束事件。具体来说&#xff0c;你可以实现以下方法&#xff1a; func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {if !decelerat…

Python 实现接口类的两种方式+邮件提醒+动态导入模块+反射(参考Django中间件源码)

实现抽象类的两种方式 方式一 from abc import ABCMeta from abc import abstractmethodclass BaseMessage(metaclassABCMeta):abstractmethoddef send(self,subject,body,to,name):pass 方式二 class BaseMessage(object):def send(self, subject, body, to, name):raise …

vue3使用响应式数据 + v-model导致响应式失效el-form表单无法输入的问题

文章目录 vue3使用响应式数据 v-model导致响应式失效el-form表单无法输入的问题 vue3使用响应式数据 v-model导致响应式失效el-form表单无法输入的问题 参考文章 重构vue2项目时发现的问题&#xff0c;原始项目使用的是Element-ui。 其实vue3可以使用适配的Element-plus 问…

EasyExcel读取多sheet excel异常

EasyExcel读取多sheet excel异常 场景 使用Spring Boot集成EasyExcel进行导入excel多sheet&#xff0c;执行异常 代码 file是MultipartFile&#xff0c;入参&#xff0c;主要处理流程如下 InputStream is file.getInputStream(); EasyExcel.read(is, SysDict.class, new …

Set集合类详解(附加思维导图)

目录 一、Set集合思维导图 二、set集合类常用方法 2.1、HashSet集合常用方法 2.2、TreeSet集合的使用 三、HashSet、LinkedHashSet、TreeSet的使用场景 四、list和set集合的区别 一、Set集合思维导图 二、set集合类常用方法 2.1、HashSet集合常用方法 ①&#xff1a;add…

redis面试1

Redis基础面试题 1、为什么要使用Redis做缓存 缓存的好处 使用缓存的目的就是提升读写性能。而实际业务场景下&#xff0c;更多的是为了提升读性能&#xff0c;带来更好的性 能&#xff0c;带来更高的并发量。Redis 的读写性能比 Mysql 好的多&#xff0c;我们就可以把 Mysq…

scrapy分布式+指纹去重原理

1&#xff0c;指纹去重原理存在于 scrapy.util.requests 里面 需要安装的包 pip install scrapy-redis-cluster # 安装模块 pip install scrapy-redis-cluster0.4 # 安装模块时指定版本 pip install --upgrade scrapy-redis-cluster # 升级模块版本 2&#xff0c;setting配置 …

【小白必看】利用Python生成个性化名单Word文档

文章目录 前言所需文件及文件格式说明excel数据如下word 模板如下文件目录格式及生成后的文件 导入所需的模块&#xff1a;打开 Excel 文件&#xff1a;选择工作表&#xff1a;获取数据列表&#xff1a;遍历数据并生成 Word 文档&#xff1a;完整代码结束语 前言 对于需要批量…

【MyBatis 学习一】认识MyBatis 第一个MyBatis查询

目录 一、认识MyBatis 1、MyBatis是什么&#xff1f; 2、为什么要学习MyBatis? 二、配置MyBatis环境 1、建库与建表 2、创建新项目 3、xml文件配置 &#xff08;1&#xff09;配置数据库连接 &#xff08;2&#xff09;配置 MyBatis 中的 XML 路径 三、测试&#x…

mysql(三)用户权限管理

目录 前言 一、概述 二、用户权限类型 三、用户赋权 四、权限删除 五、删除用户 前言 为什么要设置用户权限&#xff1f; MySQL设置用户管理权限的主要目的是为了确保数据库的安全性和数据的机密性。以下是一些原因&#xff1a; 1. 安全性&#xff1a;MySQL是一个开源的关系型…

Java集合之List

ArrayLsit集合 ArrayList集合的特点 ArrayList集合的一些方法 ①.add(Object element) 向列表的尾部添加指定的元素。 ②.size() 返回列表中的元素个数。 ③.get(int index) 返回列表中指定位置的元素&#xff0c;index从0开始。 public class Test {public static void m…

dependency walker工具简介及使用

dependency walker工具 简介使用 简介 官方概述&#xff1a; Dependency Walker is a free utility that scans any 32-bit or 64-bit Windows module (exe, dll, ocx, sys, etc.) and builds a hierarchical tree diagram of all dependent modules. For each module found, …

C++ 核心编程

一、 内存分区模型 C程序在执行时&#xff0c;将内存大方向划分为4个区域 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理 全局区&#xff1a;存放全局变量和静态变量以及常量 栈区&#xff1a;由编译器自动分配释放&#xff0c;存放函数的参数值、…

gensim conherence model C_V 值与其他指标负相关BUG

在我用gensim3.8.3 conherence model分析京东评论主题模型时&#xff0c; C_V 与npmi、u_mass出现了强烈的皮尔逊负相关&#xff1a; 这些地方也反映了类似问题&#xff1a; https://github.com/dice-group/Palmetto/issues/12 https://github.com/dice-group/Palmetto/issue…

测等保2.0——安全区域边界

一、前言 今天我们来说说安全区域边界&#xff0c;顾名思义&#xff0c;安全区域边界就是保障网络边界处&#xff0c;包括网络对外界的边界和内部划分不同区域的交界处&#xff0c;我们的重点就是查看这些边界处是否部署必要的安全设备&#xff0c;包括防火墙、网闸、网关等安…