Spring mvc通过访问者IP限制接口访问频率

我们有的时候系统里面有的用户接口为了控制访问频率,需要使用到,笔记走一波

环境:

spring

spring mvc

Guava:谷歌高并发工具,下面是maven


        
            com.google.guava
            guava
            18.0
        

我们这次主要使用到的是Guava工具的LoadingCache 和 

RateLimiter 即缓存和限流
 

由于是在spring 环境中,所以就直接上Service代码了:


/**
 * 接口访问限流service,此接口主要用于针对ip地址对于接口访问的限流控制
 */
@Service
public class LoadingCacheServiceImpl implements LoadingCacheService {
    LoadingCache ipRequestCaches = CacheBuilder.newBuilder()
            .maximumSize(200)// 设置缓存个数
            .expireAfterWrite(1, TimeUnit.DAYS)
            .build(new CacheLoader() {
                @Override
                public RateLimiter load(String s) throws Exception {
                    return RateLimiter.create(0.2);// 新的IP初始化 (限流每秒0.1个令牌响应,即10s一个令牌)
                }
            });
    public RateLimiter getRateLimiter(String key) throws ExecutionException {
        return ipRequestCaches.get(key);
    }
}

控制器使用代码:

@Controller
@RequestMapping("/tool/upload/")
public class FileUploadController{
    @Resource
    LoadingCacheService loadingCacheService;
    /**
     * ajax上传文件
     * @param file 文件对象
     * @return
     */
    @RequestMapping("ajaxUpload")
    @ResponseBody
    public AjaxRes ajaxUpload(@RequestParam("file") MultipartFile file, HttpServletRequest httpServletRequest){
        String ipAddr = IPUtil.getIpAddr(getRequest());
        try {
            RateLimiter limiter = loadingCacheService.getRateLimiter(ipAddr);
            if(limiter.tryAcquire()){
                //获得令牌(不限制访问)
            }else {
                //未获得令牌(限制访问)
            }
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return res;
    }
}

注:主要就是把没一个用户IP的令牌桶RateLimiter给缓存起来,然后每次用户请求接口的时候就去拿一次令牌,那到令牌则不限制访问,没拿到则限制

PS:第一次使用,哪里不对请指正,谢谢

 

根据qq_35284533兄弟的提示,补充IPUtil工具类代码,这个工具类是用于获取IP地址的。

package com.jufanshare.myblog.common.util;

import javax.servlet.http.HttpServletRequest;

/**
 * 获取客户端IP地址
 */
public class IPUtil {
	
	/**
	 * 客户端真实IP地址的方法一:
	 */
	public static String getRemortIP(HttpServletRequest request) {
	    if (request.getHeader("x-forwarded-for") == null) {  
	        return request.getRemoteAddr();  
	    }  
	    return request.getHeader("x-forwarded-for");  
	}  
	/**
	 * 客户端真实IP地址的方法二:
	 */
	public static String getIpAddr(HttpServletRequest request) {
		String ip="";
		if(request!=null){
			 ip = request.getHeader("x-forwarded-for");  
			    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			        ip = request.getHeader("Proxy-Client-IP");  
			    }  
			    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			        ip = request.getHeader("WL-Proxy-Client-IP");  
			    }  
			    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			        ip = request.getRemoteAddr();  
			    }  
		}
	    return ip;  
	}  
}

 

 

 

你可能感兴趣的:(高并发)