限制ip访问频率

本文介绍了一个Java实现的IP基于滑动窗口速率限制器,它使用ConcurrentHashMap和ConcurrentSkipListMap来管理每个IP地址的请求记录,每1000毫秒内限制同一IP访问两次。
摘要由CSDN通过智能技术生成

需求是每1000毫秒内,只允许同一个ip访问2次

效果如图:

在这里插入图片描述

代码如下:


import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Calendar;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;

import java.util.concurrent.atomic.AtomicInteger;

class RequestRecord {
    private final Instant timestamp;
    private final AtomicInteger count = new AtomicInteger(1);

    public RequestRecord(Instant timestamp) {
        this.timestamp = timestamp;
    }

    public Instant getTimestamp() {
        return timestamp;
    }

    public int getCount() {
        return count.get();
    }

    public void increment() {
        count.incrementAndGet();
    }
}


class SlidingWindowRateLimiter {
    private final ConcurrentSkipListMap<Instant, RequestRecord> records;
    private final long windowSizeInMillis;
    private final int limit;

    public SlidingWindowRateLimiter(long windowSizeInMillis, int limit) {
        this.records = new ConcurrentSkipListMap<>();
        this.windowSizeInMillis = windowSizeInMillis;
        this.limit = limit;
    }

    public synchronized boolean allowRequest() {
        Instant now = Instant.now();
        // 移除窗口外的旧记录
        records.headMap(now.minusMillis(windowSizeInMillis)).clear();

        // 检查当前窗口内是否已达到请求限制
        int totalRequests = records.values().stream().mapToInt(RequestRecord::getCount).sum();
        if (totalRequests >= limit) {
            return false;
        }

        // 添加当前请求记录
        records.compute(now, (key, value) -> {
            if (value == null) {
                return new RequestRecord(now);
            } else {
                value.increment();
                return value;
            }
        });
        return true;
    }
}

public class IPBasedSlidingWindowRateLimiter {
    private final ConcurrentMap<String, SlidingWindowRateLimiter> ipRateLimiters;
    private final long windowSizeInMillis;
    private final int limitPerWindow;

    public IPBasedSlidingWindowRateLimiter(long windowSizeInMillis, int limitPerWindow) {
        this.ipRateLimiters = new ConcurrentHashMap<>();
        this.windowSizeInMillis = windowSizeInMillis;
        this.limitPerWindow = limitPerWindow;
    }

    public synchronized boolean allowRequest(String ipAddress) {
        SlidingWindowRateLimiter limiter = ipRateLimiters.computeIfAbsent(ipAddress,
                k -> new SlidingWindowRateLimiter(windowSizeInMillis, limitPerWindow));
        return limiter.allowRequest();
    }

    public static String curDateTimeStr() {
        Calendar calendar2 = Calendar.getInstance();
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf2.format(calendar2.getTime());
    }


    public static void main(String[] args) throws InterruptedException {
        // http请求根据ip限制频率
        IPBasedSlidingWindowRateLimiter rateLimiter = new IPBasedSlidingWindowRateLimiter(1000, 2);
        String ip = "1.1.1.1";
        String ip2 = "2.2.2.2";
        for (int i = 0; i < 200; i++) {
            if (rateLimiter.allowRequest(ip)) {
                System.out.println("["+curDateTimeStr()+"] "+i+":允许访问"+ip);
            } else {
                System.out.println("["+curDateTimeStr()+"] "+i+":访问受限"+ip + "," + (rateLimiter.allowRequest(ip2) ? "允许访问"+ip2 : "访问受限"+ip2));
                Thread.sleep(2000L);
            }
        }
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用Nginx的模块来限制同一IP访问频率。其中一个常用的模块是ngx_http_limit_req_module,它可以帮助您实现这个目标。 要使用该模块,请按照以下步骤进行操作: 1. 打开您的Nginx配置文件,通常位于 `/etc/nginx/nginx.conf` 或 `/etc/nginx/conf.d/default.conf`。 2. 在适当的位置(例如 `http` 块内),添加以下配置: ``` http { # 设置限制频率的zone limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; # 设置限制频率的规则 server { location / { # 使用之前定义的zone进行限制 limit_req zone=one burst=5; # 其他配置项... } } # 其他配置项... } ``` 在上述配置中,`limit_req_zone` 定义了一个名为 `one` 的zone,使用 `$binary_remote_addr` 来标识每个IP地址。`10m` 是用于存储限制信息的内存大小,您可以根据实际情况进行调整。`rate=1r/s` 表示每秒允许一个请求。 在 `server` 块内的 `location` 配置中,使用 `limit_req zone=one burst=5` 来应用限制规则。`burst` 参数表示在超过限制频率时允许的突发请求数量。 3. 保存配置文件并重新加载Nginx,以使更改生效。您可以使用以下命令重新加载Nginx: ``` sudo systemctl reload nginx ``` 这样,Nginx就会根据配置限制同一IP访问频率。当超过设定的限制时,Nginx会返回一个503错误给客户端。 请注意,您可以根据需要调整 `limit_req_zone` 和 `limit_req` 的参数,以满足您的具体需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值