wildfire chat server source initial submit
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user