使用redis incr计数来控制单位时间内对某接口的访问量
生活随笔
收集整理的這篇文章主要介紹了
使用redis incr计数来控制单位时间内对某接口的访问量
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
控制單位時間內接口的訪問量
使用redis incr計數來控制單位時間內對某接口的訪問量,防止刷驗證碼接口之類的。
使用自定義注解的方式,在需要被限制訪問頻率的方法上加注解即可控制。
看實現方式,基于springboot,aop,redis。
新建Springboot工程,引入redis,aop。
創建注解
package com.xueliang.annotation;import org.springframework.core.Ordered; import org.springframework.core.annotation.Order;import java.lang.annotation.*;/*** Created by xueliang on 17/7/6.*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented //最高優先級 @Order(Ordered.HIGHEST_PRECEDENCE) public @interface RequestLimit {/*** 允許訪問的次數*/int count() default 5;/*** 時間段,多少時間段內運行訪問count次*/long time() default 60000;}Aspect切面處理邏輯
package com.xueliang.aspect;import com.xueliang.annotation.RequestLimit; import com.xueliang.util.HttpRequestUtil; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest; import java.util.concurrent.TimeUnit;/*** Created by xueliang on 17/7/6.*/ @Component @Aspect public class RequestLimitAspect {private final Logger logger = LoggerFactory.getLogger(getClass());@Autowiredprivate RedisTemplate<String, String> redisTemplate;@Before("execution(public * com.xueliang.controller.*.*(..)) && @annotation(limit)")public void requestLimit(JoinPoint joinpoint, RequestLimit limit) {// 接收到請求,記錄請求內容ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();String ip = HttpRequestUtil.getIpAddr(request);String url = request.getRequestURL().toString();String key = "req_limit_".concat(url).concat(ip);//加1后看看值long count = redisTemplate.opsForValue().increment(key, 1);//剛創建if (count == 1) {//設置1分鐘過期redisTemplate.expire(key, limit.time(), TimeUnit.MILLISECONDS);}if (count > limit.count()) {logger.info("用戶IP[" + ip + "]訪問地址[" + url + "]超過了限定的次數[" + limit.count() + "]");throw new RuntimeException("超出訪問次數限制");}} }獲取IP的工具類
package com.xueliang.util;import javax.servlet.http.HttpServletRequest; import java.net.InetAddress; import java.net.UnknownHostException;/*** Created by xueliang on 17/7/6.*/ public class HttpRequestUtil {/*** 獲取當前網絡ip** @param request* @return*/public static String getIpAddr(HttpServletRequest request) {String ipAddress = request.getHeader("x-forwarded-for");if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("WL-Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddr();if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {//根據網卡取本機配置的IPInetAddress inet = null;try {inet = InetAddress.getLocalHost();} catch (UnknownHostException e) {e.printStackTrace();}ipAddress = inet.getHostAddress();}}//對于通過多個代理的情況,第一個IP為客戶端真實IP,多個IP按照','分割if (ipAddress != null && ipAddress.length() > 15) { //"***.***.***.***".length() = 15if (ipAddress.indexOf(",") > 0) {ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));}}return ipAddress;} }通過Controller驗證
@RestController public class IndexController {@RequestLimit(count = 4)@GetMapping("/index")public Object index() {return 1;} }啟動工程,使用jmeter多次訪問index看看效果即可。
總結
以上是生活随笔為你收集整理的使用redis incr计数来控制单位时间内对某接口的访问量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Solr的安装步骤及增删改查代码示例
- 下一篇: JVM 参数含义:-Xms和-Xmx