Files
IM-server-new/broker/src/main/java/win/liyufan/im/FrequencyLimistCounter.java
T

141 lines
4.0 KiB
Java

package win.liyufan.im;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 频率限制计数器,由于线程并发问题,并不一定严格准确,但总体可用
*/
public class FrequencyLimistCounter {
private final Map<String, Integer> CACHE_MAP = new HashMap<>();
private final Map<String, Long> CACHE_TIME_MAP = new HashMap<>();
private long CACHE_HOLD_TIME = 5 * 1000;
private int FREQUENCY_LIMIT = 100;
private final SpinLock mLock = new SpinLock();
private long lastFullScanTime = System.currentTimeMillis();
//2个小时全部扫描一次
private static final long fullScanDuration = 2*60*60*1000;
public FrequencyLimistCounter(int limitTimeSec, int limitCount) {
this.CACHE_HOLD_TIME = limitTimeSec * 1000;
this.FREQUENCY_LIMIT = limitCount;
}
public FrequencyLimistCounter() {
}
/**
* 增加对象计数并返回是否超频
* @param cacheName
* @return ture 超频; false 不超频
*/
public boolean increaseAndCheck(String cacheName) {
mLock.lock();
try {
tryFullScan();
Long cacheHoldTime = CACHE_TIME_MAP.get(cacheName);
if (cacheHoldTime != null && cacheHoldTime < System.currentTimeMillis()) {
CACHE_MAP.remove(cacheName);
CACHE_TIME_MAP.remove(cacheName);
}
Integer count = CACHE_MAP.get(cacheName);
if (count != null) {
CACHE_MAP.put(cacheName, ++count);
} else {
count = 0;
CACHE_MAP.put(cacheName, ++count);
CACHE_TIME_MAP.put(cacheName, (System.currentTimeMillis() + CACHE_HOLD_TIME));//缓存失效时间
}
if (count >= FREQUENCY_LIMIT) {
return true;
}
return false;
} finally {
mLock.unLock();
}
}
//去掉超时的数据,如果在一个低频使用的系统中,会残留大量超时无用的信息
private void tryFullScan() {
if (System.currentTimeMillis() - lastFullScanTime > fullScanDuration) {
lastFullScanTime = System.currentTimeMillis();
for (Map.Entry<String, Long> entry : CACHE_TIME_MAP.entrySet()
) {
if (entry.getValue() < lastFullScanTime) {
CACHE_MAP.remove(entry.getKey());
CACHE_TIME_MAP.remove(entry.getKey());
}
}
}
}
public static void main(String[] args) {
FrequencyLimistCounter counter = new FrequencyLimistCounter(5, 100);
String name = "test";
for (int i = 0; i < 50; i++) {
if(counter.increaseAndCheck(name)) {
System.out.println("test failure 1");
System.exit(-1);
}
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 49; i++) {
if(counter.increaseAndCheck(name)) {
System.out.println("test failure 2");
System.exit(-1);
}
}
if(!counter.increaseAndCheck(name)) {
System.out.println("test failure 3");
System.exit(-1);
}
try {
Thread.sleep(5*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 99; i++) {
if(counter.increaseAndCheck(name)) {
System.out.println("test failure 4");
System.exit(-1);
}
}
try {
Thread.sleep(5*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 99; i++) {
if(counter.increaseAndCheck(name)) {
System.out.println("test failure 5");
System.exit(-1);
}
}
}
}