根据登陆ip,限制1分钟最多10次服务请求,须支持单机并发场景,请使用java代码原生实现

       由于业务系统服务接口被竞对高频爬取,我们需要上线一个防刷限流功能。场景要求如下:根据登陆ip,限制1分钟最多10次服务请求,须支持单机并发场景,请使用java代码原生实现(勿使用中间件redis、计数器之类方案)。

// 请完善如下模板代码

public class Solution {
        //不限流返回ture,限流返回false
        public boolean access(String ip) {
        // @todo
            return false;
        }
    }

废话不多说直接贴代码(注意!注意!注意!重要的事说三遍在线程超过150条的情况下,有几率会代码容错(超过10次正确请求,测了5都超不过11次),120条线程以下绝不会发生,所以此时就有了解决方法,采用信号量分批放线程,10条线程最安全,别问,问就是前10条全部成功,后面在规定时间内全部失败

 要是不想自己动手贴上gitee仓库地址自己克隆:

                          试题Java代码https://gitee.com/jiuguanxiaojiu/java-written-test-questions 

代码在bool里,如若不会克隆请移步 

      Git生成ssh公私钥,连接getee仓库克隆代码 https://blog.csdn.net/m0_59849460/article/details/123819669

http测试类 

package com.it.juxiang.demo.bool;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;


/**
 * 模拟同一用户快速多次登录(请求),通过(UserLoginLimiter)限制
 *
 */


@Controller
public class UserLoginTimeController {
    @Autowired
    private UserLoginLimiter userLoginLimiter;


    @PostMapping("/bool")
    @ResponseBody
    public String test() {
        String ip="192.168.198.10";
        if (userLoginLimiter.check(ip)) {
            System.out.println(ip + ":访问成功:true...........!");
            return (ip + ":访问成功:true!");
        } else {
            System.out.println(ip +":访问失败:false!");
            return (ip + ":访问失败:false!");
        }
    }
    
}

 核心代码(答案)

package com.it.juxiang.demo.bool;

import org.springframework.stereotype.Component;

import java.util.LinkedList;

/**
 * 用户登录记录限制类
 * 限制在一定时长(thresholdInMillisecond)内最多登录(maxLoginTimes)次
 */
@Component
public class UserLoginLimiter {
    //默认限制器,限制在60秒之内最多访问10次
    private int maxLoginTimes=10; //一定时间(thresholdInMillisecond值)内的最多登录次数
    private int thresholdInMillisecond=60000; //时长
    private LinkedList<LoginRecord> loginRecordList=new LinkedList<LoginRecord>(); //最近的登录队列



    /**
     * 检查登录记录,
     * 对在(thresholdInMillisecond)时长内超过(maxloginTimes)次的登录记录返回false,否则返回true;
     * @param ip
     * @return
     */
    public boolean check(String ip) {

        //检查设置的值,对0及负数表示不限制登录
        if (maxLoginTimes <= 0 || thresholdInMillisecond <= 0) return true;

        LoginRecord loginRecord=new LoginRecord(ip,System.currentTimeMillis());

        //队列长度未到maxLoginTimes的不用限制
        if (loginRecordList.size() < maxLoginTimes) {
            loginRecordList.addLast(loginRecord);
            return true;
        }

        //队列长度达到maxLoginTimes的,清理和当前记录比较超过thresholdInMillisecond值的记录
        LoginRecord firstLR = loginRecordList.getFirst();
        while (loginRecordList.size() > 0 && firstLR.getTime() + thresholdInMillisecond < loginRecord.getTime()) {
            loginRecordList.removeFirst();
            if (loginRecordList.size() > 0) {
                firstLR = loginRecordList.getFirst();
            } else {
                break;
            }
        }

        //检查队列是否有空间添加新的记录
        if (loginRecordList.size() < maxLoginTimes) {
            loginRecordList.addLast(loginRecord);
            return true;
        } else {
            return false; //队列中的记录与当前登录记录发生在thresholdInMillisecond内,拒绝
        }
    }

}

 用户登录记录类

package com.it.juxiang.demo.bool;

/**
 * 用户登录记录类
 */
public class LoginRecord {
    private String ip;
    private long time;

    public LoginRecord(String ip, long time) {
        this.ip = ip;
        this.time = time;
    }

    public String getIp() {
        return ip;
    }

    public long getTime() {
        return time;
    }


    @Override
    public String toString() {
        return "LoginRecord{" +
                "ip='" + ip + '\'' +
                ", time=" + time +
                '}';
    }
}

 推荐一个软件,可以方便测试多线程下的运行:

Apache JMeter WEB

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酒馆小酒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值