用户缓存逻辑修改
parent
88689a9824
commit
980635e41a
|
|
@ -4,13 +4,9 @@ import com.ljsd.jieling.logic.dao.UserManager;
|
|||
import com.ljsd.jieling.netty.cocdex.PacketNetData;
|
||||
import com.ljsd.jieling.network.session.ISession;
|
||||
import com.ljsd.jieling.util.MessageUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import rpc.protocols.MessageTypeProto;
|
||||
import rpc.protocols.PlayerInfoProto;
|
||||
|
||||
public class LoginConfirmHandler extends BaseHandler{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LoginRequestHandler.class);
|
||||
|
||||
@Override
|
||||
public MessageTypeProto.MessageType getMessageCode() {
|
||||
|
|
@ -20,8 +16,7 @@ public class LoginConfirmHandler extends BaseHandler{
|
|||
@Override
|
||||
public void process(ISession iSession, PacketNetData netData) throws Exception {
|
||||
UserManager.loginConfirm();
|
||||
MessageUtil.sendMessage(iSession,1,
|
||||
MessageTypeProto.MessageType.LOGIN_CONFIRM_RESPONSE.getNumber(),null,true);
|
||||
MessageUtil.sendMessage(iSession,1, MessageTypeProto.MessageType.LOGIN_CONFIRM_RESPONSE.getNumber(),null,true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ package com.ljsd.jieling.logic;
|
|||
|
||||
import com.ljsd.jieling.logic.dao.UserManager;
|
||||
import com.ljsd.jieling.network.session.ISession;
|
||||
import org.springframework.data.redis.support.collections.DefaultRedisMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
|
@ -20,7 +18,7 @@ public class OnlineUserManager {
|
|||
public static Map<Integer,Integer> tokenMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static void checkOnline(){
|
||||
UserManager.checkOffline();
|
||||
UserManager.adjustCacheBasedOnCurrentLoad();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import com.ljsd.jieling.logic.mission.GameEvent;
|
|||
import com.ljsd.jieling.logic.mission.MissionType;
|
||||
import com.ljsd.jieling.logic.player.PlayerLogic;
|
||||
import com.ljsd.jieling.logic.store.newRechargeInfo.NewRechargeInfo;
|
||||
import com.ljsd.jieling.util.DynamicLRUCache;
|
||||
import com.ljsd.jieling.util.ItemUtil;
|
||||
import com.ljsd.jieling.util.SysUtil;
|
||||
import config.SGameSetting;
|
||||
|
|
@ -33,33 +34,26 @@ import util.TimeUtils;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class UserManager {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(UserManager.class);
|
||||
private static Map<Integer, User> userMap = new ConcurrentHashMap<>();
|
||||
private static Map<Integer, Long> userMapPutTime = new ConcurrentHashMap<>(); //离线读入
|
||||
/**
|
||||
* 记录用户被请求过几次,只记录离线用户,每请求一次+1,每分钟-1,为0时删除缓存
|
||||
*/
|
||||
private final static Map<Integer, Integer> userCount = new HashMap<>();
|
||||
private static AtomicInteger login_f_num = new AtomicInteger(0);//登陆计数
|
||||
private static final int LOGIN_F_LIMIT = 100;//报警界限
|
||||
private static final long LIVE_TIME = 3 * 60 * 60 * 1000L;
|
||||
// 玩家数据缓存
|
||||
private static final int maxMemoryLimit = 1000; // 最大内存限制,实际应由您的服务器规格决定
|
||||
private static final long LIVE_TIME = 60 * 60 * 1000L;// 离线玩家缓存保留时间(毫秒)
|
||||
private static final DynamicLRUCache<Integer, User> userMap = new DynamicLRUCache<>(100, LIVE_TIME);
|
||||
private static final AtomicInteger login_f_num = new AtomicInteger(0);//登陆计数
|
||||
|
||||
|
||||
public static void addUser(User user) {
|
||||
int uid = user.getId();
|
||||
userMap.put(uid, user);
|
||||
userMapPutTime.put(uid,TimeUtils.now());
|
||||
userMap.put(user.getId(), user);
|
||||
}
|
||||
|
||||
public static void removeUser(int uid) {
|
||||
userMap.remove(uid);
|
||||
userMapPutTime.remove(uid);
|
||||
userCount.remove(uid);
|
||||
}
|
||||
|
||||
public static boolean isUserExist(int uid) {
|
||||
|
|
@ -67,53 +61,34 @@ public class UserManager {
|
|||
}
|
||||
|
||||
public static int getUserMapSize() {
|
||||
return userMap.keySet().size();
|
||||
return userMap.size();
|
||||
}
|
||||
|
||||
public static int getCurrentOnlinePlayers() {
|
||||
// 实际的在线玩家数量检索逻辑...
|
||||
return OnlineUserManager.sessionMap.size();
|
||||
}
|
||||
|
||||
// 这个方法可能由定时任务或某种监控服务调用
|
||||
public static void adjustCacheBasedOnCurrentLoad() {
|
||||
// 调用缓存的调整方法来根据在线玩家数量调整缓存大小
|
||||
userMap.shrinkToFit();
|
||||
}
|
||||
|
||||
//离线清除逻辑
|
||||
public static void checkOffline(){
|
||||
try {
|
||||
// LOGGER.info("user map value size is {}", RamUsageEstimator.humanSizeOf(userMap));
|
||||
Set<User> collect = userMap.entrySet().stream()
|
||||
.filter(integerUserEntry -> !OnlineUserManager.checkUidOnline(integerUserEntry.getKey()))
|
||||
.map(Map.Entry::getValue).collect(Collectors.toSet());
|
||||
long now = System.currentTimeMillis();
|
||||
for (User integerUserEntry : collect) {
|
||||
Long addTime = userMapPutTime.getOrDefault(integerUserEntry.getId(), LIVE_TIME);
|
||||
if (now - addTime >= LIVE_TIME) {
|
||||
removeUser(integerUserEntry.getId());
|
||||
}
|
||||
}
|
||||
LOGGER.info("checkOffline left count={}", userMap.keySet().size());
|
||||
}catch (Exception e){
|
||||
LOGGER.error("Exception离线清除逻辑err={}",e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void userClear(){
|
||||
// public static void checkOffline(){
|
||||
// try {
|
||||
// Iterator<Map.Entry<Integer, User>> iterator = userMap.entrySet().iterator();
|
||||
// while (iterator.hasNext()){
|
||||
// Map.Entry<Integer, User> next = iterator.next();
|
||||
// Integer uid = next.getKey();
|
||||
// if (OnlineUserManager.checkUidOnline(uid)){
|
||||
// long now = TimeUtils.now();
|
||||
// for (User user : userMap.getAll()) {
|
||||
// if (OnlineUserManager.checkUidOnline(user.getId())){
|
||||
// continue;
|
||||
// }
|
||||
// Integer count = userCount.getOrDefault(uid, 0);
|
||||
// if (count-- <= 0){
|
||||
// MongoUtil.getLjsdMongoTemplate().lastUpdate();
|
||||
// LOGGER.info("离线玩家{}被请求次数为{},剔除缓存",uid,count);
|
||||
// iterator.remove();
|
||||
// removeUser(uid);
|
||||
// }else {
|
||||
// userCount.put(uid,count);
|
||||
// }
|
||||
// }
|
||||
// LOGGER.info("checkOffline left count={}", getUserMapSize());
|
||||
// }catch (Exception e){
|
||||
// LOGGER.error("userClear报错{}",e);
|
||||
// LOGGER.error("Exception离线清除逻辑err={}",e.toString());
|
||||
// }
|
||||
}
|
||||
|
||||
// }
|
||||
|
||||
public static User userLogin(int uid,String openId,String channel,int pid,int gid,String platform,String ip,String channle_id,String bundle_id,String ccId,String pack_Id) throws Exception {
|
||||
User user;
|
||||
|
|
@ -212,9 +187,7 @@ public class UserManager {
|
|||
|
||||
public static User getUser(int uid,boolean canNull) throws Exception {
|
||||
User user = userMap.get(uid);
|
||||
if (user != null) {
|
||||
userMapPutTime.put(uid, TimeUtils.now());
|
||||
}else {
|
||||
if (user == null) {
|
||||
user = MongoUtil.getInstence().getMyMongoTemplate().findById(User.getCollectionName(), uid, User.class);
|
||||
if (null == user) {
|
||||
if(!canNull){
|
||||
|
|
@ -224,7 +197,6 @@ public class UserManager {
|
|||
UserManager.addUser(user);
|
||||
}
|
||||
}
|
||||
userCount.put(uid,userCount.getOrDefault(uid,0)+1);
|
||||
return user;
|
||||
}
|
||||
|
||||
|
|
@ -241,8 +213,9 @@ public class UserManager {
|
|||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
public static void loginIncrease(){
|
||||
if(login_f_num.incrementAndGet() >= LOGIN_F_LIMIT){
|
||||
if(login_f_num.incrementAndGet() >= 100){
|
||||
String path = SysUtil.getPath("conf/loginerror/loginerror"+ GameApplication.serverId +".txt");
|
||||
File file = new File(path);
|
||||
try{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.ljsd.jieling.network.server;
|
||||
|
||||
import com.ljsd.jieling.exception.ErrorCode;
|
||||
import com.ljsd.jieling.logic.OnlineUserManager;
|
||||
import com.ljsd.jieling.logic.dao.UserManager;
|
||||
import com.ljsd.jieling.network.session.ISession;
|
||||
import com.ljsd.jieling.util.MessageUtil;
|
||||
import io.netty.util.internal.ConcurrentSet;
|
||||
|
|
@ -20,7 +20,7 @@ public class Blocker {
|
|||
private static ConcurrentSet<Integer> forbidLogin = new ConcurrentSet<>();
|
||||
|
||||
public static boolean checkForbidUser(ISession iSession){
|
||||
if(forbidLogin.size()<1){
|
||||
if(forbidLogin.isEmpty()){
|
||||
return false;
|
||||
}
|
||||
if(iSession!=null) {
|
||||
|
|
@ -35,7 +35,7 @@ public class Blocker {
|
|||
|
||||
public static boolean checkFlow(ISession iSession){
|
||||
if(iSession!=null) {
|
||||
if(OnlineUserManager.sessionMap.size()>maxAllowedOnlineAccountCount.get()){
|
||||
if(UserManager.getCurrentOnlinePlayers() > maxAllowedOnlineAccountCount.get()){
|
||||
MessageUtil.sendErrorCode(iSession, ErrorCode.ONLINE_FLOW.code(), "当前在线人数过多,请稍等哦!");
|
||||
iSession.setOfflineType(ErrorCode.reloginCode);
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -390,31 +390,27 @@ public class SessionManager implements INetSession<ISession>, INetReceived<ISess
|
|||
iSession.setHeartBreatNums(heartBreatNums);
|
||||
}
|
||||
|
||||
public boolean kickOldUser(int uid, String uToken, int errorCode, String errorMsg, long requestTime) {
|
||||
if (OnlineUserManager.sessionMap.size() != 0 && OnlineUserManager.sessionMap.keySet().contains(uid)) {
|
||||
public void kickOldUser(int uid, String uToken, int errorCode, String errorMsg, long requestTime) {
|
||||
if (!OnlineUserManager.sessionMap.isEmpty() && OnlineUserManager.sessionMap.containsKey(uid)) {
|
||||
if (requestTime != 0 && requestTime < OnlineUserManager.sessionMap.get(uid).getUserLoginTime()) {
|
||||
LOGGER.info("kickOldUser->uid={},requestTime={},userLoginTime={}",
|
||||
uid, requestTime, OnlineUserManager.sessionMap.get(uid).getUserLoginTime());
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!OnlineUserManager.checkUidOnline(uid)) {
|
||||
LOGGER.info("kickOldUser->uid={};isNotOnline", uid);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
ISession oldSession = OnlineUserManager.getSessionByUid(uid);
|
||||
if (oldSession == null) {
|
||||
LOGGER.info("kickOldUser->uid={};oldSessionisNull", uid);
|
||||
OnlineUserManager.userOffline(uid);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
oldSession.setOfflineType(errorCode);
|
||||
|
||||
|
||||
offLine(oldSession);
|
||||
oldSession.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ public class MinuteTask extends Thread {
|
|||
public void run() {
|
||||
try {
|
||||
LOGGER.info("MinuteTask start... online use num::{} memory user count={}", OnlineUserManager.sessionMap.entrySet().size(), UserManager.getUserMapSize());
|
||||
UserManager.userClear();
|
||||
//TODO 每分钟逻辑通过监听事件处理 已经迁移活动和热更新
|
||||
Poster.getPoster().dispatchEvent(new MinuteTaskEvent());
|
||||
|
||||
|
|
@ -162,7 +161,12 @@ public class MinuteTask extends Thread {
|
|||
|
||||
try {
|
||||
GuildFightLogic.minuteCheckForCarFight();
|
||||
// reportUserOnline();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Exception::=>{}", e.toString());
|
||||
}
|
||||
|
||||
try {
|
||||
OnlineUserManager.checkOnline();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
package com.ljsd.jieling.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class DynamicLRUCache<K, V> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DynamicLRUCache.class);
|
||||
private final Map<K, TimedCacheEntry<V>> cache;
|
||||
private volatile int maxSize;
|
||||
private final long expireTime;
|
||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
|
||||
public DynamicLRUCache(int maxSize, long expireTime) {
|
||||
this.maxSize = maxSize;
|
||||
this.expireTime = expireTime;
|
||||
this.cache = new LinkedHashMap<K, TimedCacheEntry<V>>(maxSize, 0.75f, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<K, TimedCacheEntry<V>> eldest) {
|
||||
return size() > maxSize || isEntryExpired(eldest.getValue());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public V get(K key) {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
TimedCacheEntry<V> entry = cache.get(key);
|
||||
if (entry != null && !isEntryExpired(entry)) {
|
||||
entry.timestamp = System.currentTimeMillis();
|
||||
return entry.value;
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void put(K key, V value) {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
if (cache.size() >= maxSize && maxSize < Integer.MAX_VALUE / 2) {
|
||||
maxSize *= 2; // 控制最大扩容限制
|
||||
}
|
||||
cache.put(key, new TimedCacheEntry<>(value));
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(K key) {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
cache.remove(key);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsKey(K key) {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return cache.containsKey(key);
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return cache.size();
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public List<V> getAll() {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
List<V> values = new ArrayList<>();
|
||||
for (TimedCacheEntry<V> entry : cache.values()) {
|
||||
if (!isEntryExpired(entry)) {
|
||||
values.add(entry.value);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void shrinkToFit() {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
if (cache.size() < maxSize / 2) {
|
||||
maxSize /= 2; // 缩小缓存容量
|
||||
}
|
||||
cache.entrySet().removeIf(entry -> isEntryExpired(entry.getValue()));
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
LOGGER.info("当前用户缓存列表大小,num:{},max:{}",size(),maxSize);
|
||||
}
|
||||
|
||||
private boolean isEntryExpired(TimedCacheEntry<V> entry) {
|
||||
return System.currentTimeMillis() - entry.timestamp > expireTime;
|
||||
}
|
||||
|
||||
private static class TimedCacheEntry<V> {
|
||||
long timestamp;
|
||||
V value;
|
||||
|
||||
TimedCacheEntry(V value) {
|
||||
this.value = value;
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue