`

使用 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 实现定时缓存功能

    本篇文章将详细探讨如何利用Guava库实现定时缓存功能,以提高应用的性能和效率。 首先,Guava的Cache组件是其核心特性之一,它提供了一种高效、自动化的缓存机制。定时缓存功能允许我们存储计算结果或从远程服务...

    基于Zookeeper和guava动态限流 源码

    我们将首先理解Zookeeper和Guava的基本概念,然后介绍它们如何协同工作以实现动态限流,最后会简要讨论如何安装和使用Zookeeper及ZKUI。 Zookeeper是Apache的一个开源项目,它是一个分布式的、开放源码的分布式应用...

    读书笔记:微服务架构实战篇五Spring boot2.x + Guava 并使用RateLimiter秒杀限流.zip

    读书笔记:微服务架构实战篇五Spring boot2.x + Guava 并使用RateLimiter秒杀限流

    分布式环境下限流方案的实现redis RateLimiter Guava,Token Bucket, Leaky Bucket1

    1. **Guava RateLimiter**:Guava库中的RateLimiter提供了基于令牌桶算法的限流功能,可以限制每秒处理的请求数量。例如,`RateLimiter.create(400)` 创建了一个每秒允许400个请求的限流器。然而,这种方法在分布式...

    springboot结合自定义注解aop实现限流

    Springboot结合自定义注解的使用 Springboot结合aop使用 接口限流思路

    Java限流实现

    在Java中,我们可以使用开源库如Guava的RateLimiter或Hystrix的Command限流功能来实现限流。SpringMVC框架提供了集成这些库的方法,例如通过AOP(面向切面编程)来实现全局的限流。 3. **Guava的RateLimiter**:...

    springboot通用限流代码

    本篇将详细介绍如何在Spring Boot中实现通用限流,包括集成Guava和Sentinel等流行的限流库,并探讨如何将限流功能插件化,便于复用和管理。 首先,我们来看Guava限流。Guava的RateLimiter是一个简单而强大的工具,...

    SpringBoot使用Guava实现日志脱敏

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

    java实现限流,封装的工具类

    本文将深入探讨如何利用Java实现限流,并关注于使用Semaphore作为令牌桶和漏桶算法的实现,以及在数据线程数量限制上的应用。 首先,我们需要了解限流的基本概念。限流的主要目标是确保系统在高负载下仍能保持稳定...

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

    在本文中,我们将使用 Guava 库来实现 RateLimit,主要介绍了 RateLimit 的概念、常用的限流算法、Guava 中的 RateLimiter 工具类的使用。 一、问题描述 在现实生活中,我们经常会遇到一些突发的情况,例如某天 A ...

    springboot+redis实现网站限流和接口防刷功能.zip

    在现代Web应用开发中,网站限流和接口防刷功能是至关重要的安全措施。通过结合Spring Boot和Redis,我们可以构建一套高效且灵活的限流系统,保护我们的服务免受恶意攻击,确保系统的稳定运行。本文将详细介绍如何...

    详解Java分布式IP限流和防止恶意IP攻击方案

    同时,也可以使用其他技术和工具来实现限流和防止恶意IP攻击,例如使用机器学习算法来识别恶意IP。 本文提供了一种可行的Java分布式IP限流和防止恶意IP攻击方案,希望能够帮助开发者和架构师更好地解决分布式系统中...

    不加密Google Guava视频教程.txt

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

    限流代码脚本

    在Java中,Spring Cloud Gateway 提供了RateLimiter过滤器,可以基于Guava的RateLimiter实现限流。 以下是一个简单的Python限流示例,使用了`ratelimiter`库: ```python from ratelimiter import RateLimiter # ...

    guava使用方法教程

    guava 使用方法 教程

    SpringCloud Zuul过滤器和谷歌Gauva实现限流

    在本篇文章中,我们将主要介绍如何使用 SpringCloud Zuul 过滤器和谷歌 Guava 实现限流。限流是指对服务的并发请求数量进行限制,以避免服务崩溃或性能下降。在当前的微服务架构中,限流是一种非常重要的机制,能够...

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

    除了基于`RateLimiter`的限速控制外,另一种常用的限流方式是使用Lua脚本来限制一定时间窗口内的访问量。这种方案相对宽松,不对访问速度做出严格限制,而是关注一段时间内的访问总量是否超出阈值。 ##### 4.1 Lua...

    guava-18.0(guava-18.0.jar和guava-18.0-sources.jar)

    `guava-18.0.jar`是Guava库的编译后的二进制版本,包含了所有Guava类和方法的字节码,开发者可以直接在项目中引用这个JAR文件来使用Guava的功能。Guava 18.0版本包含了大量实用工具,例如: 1. **集合框架扩展**:...

    Guava使用培训教程

    该库包含了集合、缓存、原生类型支持、并发库、常见注解、字符串处理、I/O等多方面的功能,能够帮助开发者在不增加额外依赖的情况下实现更为简洁、高效的代码编写。 ### Strings处理 #### Joiner(合并字符串) `...

Global site tag (gtag.js) - Google Analytics