`

使用 guava 实现网站某个URL限流功能

阅读更多

1.限流类
package com.leimingtech.admin.utils;

import com.google.common.util.concurrent.RateLimiter;
import com.leimingtech.core.cache.jedis.JedisUtils;
import com.leimingtech.extend.module.payment.wechat.mobile.util.MD5Util;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
* Author by gjp, Date on 2019/9/23.
* 页面访问频率限制
*/
@Slf4j
public class PageRate {


    public static final PageRate pageRate = new PageRate();
    ConcurrentHashMap<String, RateLimiter> rateLimiterPool = new ConcurrentHashMap<String, RateLimiter>();
    //每秒钟访问次数
    private int RATE_NUM = 2;
    private int LIMIT_DATE=1000 * 60 * 60;


    public static PageRate getInstance(){
        return pageRate;
    }
    /**
     * 访问频率限制
     * @param request
     * @return
     */
    public  boolean limitReqRate(HttpServletRequest request){
        boolean flag = true;
        String url = request.getRequestURI();
        String ip = getIpAddress(request);

        StringBuffer stringBuffer =  new StringBuffer(60);
        stringBuffer.append(url).append("-").append(ip);

        String key = "LYPT:RATE:"+MD5Util.MD5Encode(stringBuffer.toString(),"UTF-8");

        //检查key值是否存在
        if(JedisUtils.exists(key)){
            log.info("该用户的ip地址已经被禁止访问,key={}",key);
            flag = false;
        }

        if (rateLimiterPool.containsKey(key)) {//已经加入计数器
            if (rateLimiterPool.get(key).tryAcquire(1, TimeUnit.SECONDS)) {
                log.info("获取的访问权限",key);
            }else {
                System.out.println("超出最大访问限制 "+key);
                JedisUtils.set(key,stringBuffer.toString(),LIMIT_DATE);
            }
        }else {
            //没有加入计数器
            log.info("加入访问权限列表",key);
            RateLimiter rateLimiter = RateLimiter.create(RATE_NUM);
            rateLimiterPool.put(key, rateLimiter);

        }

        return flag;
    }


    /**
     * 获取ip地址
     * @param request
     * @return
     */
    public String getIpAddress(HttpServletRequest request) {
        String 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.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }


    /**
     * 遍历限速池
     * @return
     */
    public String listKey(){
        StringBuffer sb =new StringBuffer(100);
        Enumeration<String> enu = rateLimiterPool.keys();
        while (enu.hasMoreElements()){
            sb.append(enu.nextElement()).append("-");
        }
        return sb.toString();
    }

    /**
     * 删除 key
     * @param key
     * @return
     */
    public boolean delByKey(final String key){
        RateLimiter limiter = rateLimiterPool.remove(key);
        boolean flag =false;
        if(null !=limiter){
            flag = true;
        }
        return flag;
    }


    /**
     *
     * @param key
     * @param num
     * @return
     */
    public RateLimiter put(String key,String num){
        RateLimiter rateLimiter = RateLimiter.create(Double.parseDouble(num));
        return  rateLimiterPool.put(key,rateLimiter);
    }

    /**
     *
     * @param key
     * @param rateLimiter
     * @return
     */
    public RateLimiter put(String key,RateLimiter rateLimiter){
        return  rateLimiterPool.put(key,rateLimiter);
    }




}




2.使用限流方法

@RequestMapping(value = "/login")
    public String login(Model model,HttpServletRequest httpServletRequest) {
        //开启限流功能
        boolean rateFlag = PageRate.getInstance().limitReqRate(httpServletRequest);
        if(!rateFlag){
            return "/index/rate";
        }

        try {
            Subject subject = SecurityUtils.getSubject();
            if (subject.isAuthenticated()) {
                return "redirect:/";
            }
            return "/index/login";
        } catch (Exception e) {
            log.error("跳转登录页面异常:", e);
        }
        return null;
    }
分享到:
评论

相关推荐

    使用google guava 实现定时缓存功能

    使用google guava 实现定时缓存功能

    SpringBoot使用Guava实现日志脱敏

    Guava脱敏是指使用Google Guava库进行敏感数据的脱敏处理。脱敏是一种保护个人隐私和数据安全的技术,通过对敏感数据进行处理,将其转换为不敏感或匿名数据,以防止数据泄露和滥用。 在Guava中,脱敏通常涉及对字符...

    基于Zookeeper和guava动态限流 源码

    基于Zookeeper和guava动态限流,自行安装zookeeper和zkui

    RateLimit-使用guava来做接口限流代码示例

    主要介绍了RateLimit-使用guava来做接口限流代码示例,具有一定借鉴价值,需要的朋友可以参考下

    Guava使用培训教程

    Guava使用培训教程

    不加密Google Guava视频教程.txt

    ├─Google Guava 第25讲-Guava之RateLimiter在漏桶限流算法中的使用.wmv ├─Google Guava 第26讲-Guava之RateLimiter令牌桶算法的使用.wmv ├─Google Guava 第27讲-ListenableFuture,FutureCallBack讲解.wmv ...

    guava使用方法教程

    guava 使用方法 教程

    guava源文档

    guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档guava源文档...

    基于RateLimiter和Lua脚本限量控制实现分布式限流.docx

    Guava RateLimiter中的控制都在RateLimiter及其子类中(如SmoothBursty),本处涉及到分布式环境下的同步,因此将其解耦,令牌桶模型存储于Redis中,对其同步操作的控制放置在如下控制类,其中同步控制使用到了前面...

    java实现令牌桶限流

    限流是对某一时间窗口内的请求数进行限制,保持...常用的限流算法有令牌桶和和漏桶,而Google开源项目Guava中的RateLimiter使用的就是令牌桶控制算法。 在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流

    springboot通用限流代码

    springboot通用限流代码,详细总结了基于springboot的常用的限流解决方案,比如集成guava,sentinel等,最后以插件化的方式引入,代码拿到后可以直接使用。

    guava-17.0-API文档-中文版.zip

    赠送jar包:guava-17.0.jar; 赠送原API文档:guava-17.0-javadoc.jar; 赠送源代码:guava-17.0-sources.jar; 赠送Maven依赖信息文件:guava-17.0.pom; 包含翻译后的API文档:guava-17.0-javadoc-API文档-中文...

    guava-31.1-jre.jar

    guava

    guava-23.0-API文档-中文版.zip

    赠送jar包:guava-23.0.jar; 赠送原API文档:guava-23.0-javadoc.jar; 赠送源代码:guava-23.0-sources.jar; 赠送Maven依赖信息文件:guava-23.0.pom; 包含翻译后的API文档:guava-23.0-javadoc-API文档-中文...

    guava-23.0.zip guava.jar guava

    guava-23.0.zip guava.jar guava

    guava-18.0-API文档-中文版.zip

    赠送jar包:guava-18.0.jar; 赠送原API文档:guava-18.0-javadoc.jar; 赠送源代码:guava-18.0-sources.jar; 包含翻译后的API文档:guava-18.0-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId:...

    Guava官方教程-中文

    Google Guava是一个比较有趣的框架,它提供了很多有趣的的功能, google Guava 给开发者提供了如下常用功能: 集合(collections) 缓存(caching) 原生的类型支持(primitives support) 并发类库(concurrency ...

    guava-20.0-API文档-中文版.zip

    赠送jar包:guava-20.0.jar; 赠送原API文档:guava-20.0-javadoc.jar; 赠送源代码:guava-20.0-sources.jar; 赠送Maven依赖信息文件:guava-20.0.pom; 包含翻译后的API文档:guava-20.0-javadoc-API文档-中文...

    eclipse-guava-插件

    eclipse的guava插件,使用guava toStringHelper造成toString函数。同样适用于hashcode equals 等

    基于SpringBoot + MySQL + Redis + RabbitMQ + Guava开发的高并发商品限时秒杀系统

    本系统是使用SpringBoot开发的高并发限时抢购秒杀系统,除了实现基本的登录、查看商品列表、秒杀、下单等功能,项目中还针对高并发情况实现了系统缓存、降级和限流。 开发工具 IntelliJ IDEA + Navicat + Sublime ...

Global site tag (gtag.js) - Google Analytics