如何限制一个接口被调用多次?-限流实战

tech2025-03-27  3

引入依赖

<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>18.0</version> </dependency>

限流实现

package com.sb.rateLimiter.service; import com.google.common.util.concurrent.RateLimiter; import org.springframework.stereotype.Service; @Service public class RateLimiterService { /** * 每秒只发出5个令牌 */ RateLimiter rateLimiter = RateLimiter.create(5.0); /** * 尝试获取令牌 * @return */ public boolean tryAcquire(){ return rateLimiter.tryAcquire(); } }

自定义拦截器,在拦截器中实现限流

package com.sb.rateLimiter.interceptor; import com.sb.rateLimiter.annotation.RateLimiterAnnotation; import com.sb.rateLimiter.service.RateLimiterService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Component public class RateLimiterInterceptor implements HandlerInterceptor { @Resource private RateLimiterService accessLimitService; private Logger logger = LoggerFactory.getLogger(RateLimiterInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!(handler instanceof HandlerMethod)) { return true; } HandlerMethod handlerMethod = (HandlerMethod) handler; RateLimiterAnnotation rateLimiterAnnotation = handlerMethod.getMethod().getAnnotation(RateLimiterAnnotation.class); if(rateLimiterAnnotation == null) { return true; } if (!accessLimitService.tryAcquire()) { logger.info("限流中......"); return false; } logger.info("请求成功"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }

实现 WebMvcConfigurer 添加自定义拦截器

package com.sb.rateLimiter.config; import com.sb.rateLimiter.interceptor.RateLimiterInterceptor; import org.springframework.boot.SpringBootConfiguration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; @SpringBootConfiguration public class WebConfiguration implements WebMvcConfigurer { @Resource private RateLimiterInterceptor rateLimiterInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(rateLimiterInterceptor).addPathPatterns("/**"); } }

自定义限流注解RateLimiterAnnotation

package com.sb.rateLimiter.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface RateLimiterAnnotation { int rateLimiterNumber() default 1; }

demo测试

package com.sb.rateLimiter.controller; import com.sb.rateLimiter.annotation.RateLimiterAnnotation; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api") public class RateLimiterController { @RateLimiterAnnotation @RequestMapping(value = "/rateLimiterTest", method = RequestMethod.GET) public void rateLimiterTest() throws Exception { //业务逻辑; }

通过jmeter进行限流测试

最新回复(0)