diff --git a/serverlogic/src/main/java/com/ljsd/GameApplication.java b/serverlogic/src/main/java/com/ljsd/GameApplication.java index e62411d37..4a83025ed 100644 --- a/serverlogic/src/main/java/com/ljsd/GameApplication.java +++ b/serverlogic/src/main/java/com/ljsd/GameApplication.java @@ -1,5 +1,6 @@ package com.ljsd; +import com.ljsd.jieling.db.redis.RedisUtil; import com.ljsd.jieling.handler.BaseHandler; import com.ljsd.jieling.logic.STableManager; import com.ljsd.jieling.netty.server.NettyGameServer; @@ -7,6 +8,7 @@ import com.ljsd.jieling.network.NettyProperties; import com.ljsd.jieling.network.NettyServerAutoConfiguration; import com.ljsd.jieling.network.server.ProtocolsManager; import com.ljsd.jieling.network.session.ISessionFactory; +import com.ljsd.jieling.thread.ThreadManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; @@ -32,7 +34,6 @@ public class GameApplication { private static NettyGameServer nettyServer = null; public static int serverId = 0; // public static ServerProperties serverProperties; - public static String coreIp; public static boolean start = false; public static void main(String[] args) throws Exception { @@ -53,7 +54,14 @@ public class GameApplication { for (BaseHandler handler : gameHanderMap.values()) { protocolsManager.addHandler(handler); } + + RedisUtil.getInstence().init(configurableApplicationContext); + STableManager.initialize("com.ljsd.jieling.config"); + + ThreadManager threadManager = new ThreadManager(); + threadManager.init(configurableApplicationContext); + final NettyServerAutoConfiguration netServerConfig = configurableApplicationContext.getBean(NettyServerAutoConfiguration.class); NettyProperties properties = netServerConfig.getNettyProperties(); try { diff --git a/serverlogic/src/main/java/com/ljsd/jieling/db/redis/RedisUtil.java b/serverlogic/src/main/java/com/ljsd/jieling/db/redis/RedisUtil.java new file mode 100644 index 000000000..839eb9831 --- /dev/null +++ b/serverlogic/src/main/java/com/ljsd/jieling/db/redis/RedisUtil.java @@ -0,0 +1,654 @@ +package com.ljsd.jieling.db.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +public class RedisUtil { + + + private RedisUtil() { + } + + public static RedisUtil getInstence() { + return InnerClass.instance; + } + + private static class InnerClass { + private static final RedisUtil instance = new RedisUtil(); + } + + @Autowired + private StringRedisTemplate redisTemplate; + + + public void init(ConfigurableApplicationContext configurableApplicationContext){ + redisTemplate = configurableApplicationContext.getBean(StringRedisTemplate.class); + } + + + /** + * 指定缓存失效时间 + * + * @param key + * 键 + * @param time + * 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + if (time > 0) { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key + * 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key + * 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key + * 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete(CollectionUtils.arrayToList(key)); + } + } + } + + // ============================String============================= + /** + * 普通缓存获取 + * + * @param key + * 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key + * 键 + * @param value + * 值 + * @return true成功 false失败 + */ + public boolean set(String key, String value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + + } + + /** + * 普通缓存放入并设置时间 + * + * @param key + * 键 + * @param value + * 值 + * @param time + * 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, String value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 递增 + * + * @param key + * 键 + * @param delta + * 要增加几(大于0) + * @return + */ + public long incr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递增因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, delta); + } + + /** + * 递减 + * + * @param key + * 键 + * @param delta + * 要减少几(小于0) + * @return + */ + public long decr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递减因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, -delta); + } + + // ================================Map================================= + /** + * HashGet + * + * @param key + * 键 不能为null + * @param item + * 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key + * 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key + * 键 + * @param map + * 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key + * 键 + * @param map + * 对应多个键值 + * @param time + * 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key + * 键 + * @param item + * 项 + * @param value + * 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key + * 键 + * @param item + * 项 + * @param value + * 值 + * @param time + * 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key + * 键 不能为null + * @param item + * 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key + * 键 不能为null + * @param item + * 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * + * @param key + * 键 + * @param item + * 项 + * @param by + * 要增加几(大于0) + * @return + */ + public double hincr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * + * @param key + * 键 + * @param item + * 项 + * @param by + * 要减少记(小于0) + * @return + */ + public double hdecr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, -by); + } + + // ============================set============================= + /** + * 根据key获取Set中的所有值 + * + * @param key + * 键 + * @return + */ + public Set sGet(String key) { + try { + return redisTemplate.opsForSet().members(key); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 根据value从一个set中查询,是否存在 + * + * @param key + * 键 + * @param value + * 值 + * @return true 存在 false不存在 + */ + public boolean sHasKey(String key, Object value) { + try { + return redisTemplate.opsForSet().isMember(key, value); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将数据放入set缓存 + * + * @param key + * 键 + * @param values + * 值 可以是多个 + * @return 成功个数 + */ + public long sSet(String key, String... values) { + try { + return redisTemplate.opsForSet().add(key, values); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 将set数据放入缓存 + * + * @param key + * 键 + * @param time + * 时间(秒) + * @param values + * 值 可以是多个 + * @return 成功个数 + */ + public long sSetAndTime(String key, long time, String... values) { + try { + Long count = redisTemplate.opsForSet().add(key, values); + if (time > 0) + expire(key, time); + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 获取set缓存的长度 + * + * @param key + * 键 + * @return + */ + public long sGetSetSize(String key) { + try { + return redisTemplate.opsForSet().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 移除值为value的 + * + * @param key + * 键 + * @param values + * 值 可以是多个 + * @return 移除的个数 + */ + public long setRemove(String key, Object... values) { + try { + Long count = redisTemplate.opsForSet().remove(key, values); + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + // ===============================list================================= + + /** + * 获取list缓存的内容 + * + * @param key + * 键 + * @param start + * 开始 + * @param end + * 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key + * 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 通过索引 获取list中的值 + * + * @param key + * 键 + * @param index + * 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public Object lGetIndex(String key, long index) { + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 将list放入缓存 + * + * @param key + * 键 + * @param value + * 值 + * @return + */ + public boolean lSet(String key, String value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key + * 键 + * @param value + * 值 + * @param time + * 时间(秒) + * @return + */ + public boolean lSet(String key, String value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key + * 键 + * @param value + * 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key + * 键 + * @param value + * 值 + * @param time + * 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据索引修改list中的某条数据 + * + * @param key + * 键 + * @param index + * 索引 + * @param value + * 值 + * @return + */ + public boolean lUpdateIndex(String key, long index, String value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 移除N个值为value + * + * @param key + * 键 + * @param count + * 移除多少个 + * @param value + * 值 + * @return 移除的个数 + */ + public long lRemove(String key, long count, String value) { + try { + Long remove = redisTemplate.opsForList().remove(key, count, value); + return remove; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/serverlogic/src/main/java/com/ljsd/jieling/network/server/ProtocolsManager.java b/serverlogic/src/main/java/com/ljsd/jieling/network/server/ProtocolsManager.java index e12e95d37..aacff8201 100644 --- a/serverlogic/src/main/java/com/ljsd/jieling/network/server/ProtocolsManager.java +++ b/serverlogic/src/main/java/com/ljsd/jieling/network/server/ProtocolsManager.java @@ -196,29 +196,21 @@ public class ProtocolsManager implements ProtocolsAbstract { } final ISession session = (ISession) gameSession; PacketNetData packetNetData = new PacketNetData((byte[])obj); + + session.setUid(packetNetData.getUserId()); + session.setToken(packetNetData.getToken()); + if (packetNetData.getMsgId()==1000){ - - new Thread(new Runnable() { - - @Override - public void run() { - - Random random = new Random(); - int time = random.nextInt(6)+1; - try { - System.out.println("sleep time : "+time); - Thread.sleep(time*1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - Thread.currentThread().setName("OOOOOOOOO"); - MessageUtil.sendHeartBeat(session); - } - }).start(); - + dealHeartBeat(session); return; } + + int resultCode = checkAndRefresh(session,packetNetData); + if (resultCode != 0 ){ + MessageUtil.sendErrorCode(session); + return; + } + BaseHandler baseHandler = handlers.get(packetNetData.getMsgId()); if (baseHandler == null) { LOGGER.info("request unknow commond : " + packetNetData.getMsgId()); @@ -232,8 +224,44 @@ public class ProtocolsManager implements ProtocolsAbstract { } } + private void dealHeartBeat(ISession session) { + new Thread(new Runnable() { + @Override + public void run() { + Random random = new Random(); + int time = random.nextInt(6)+1; + try { + System.out.println("sleep time : "+time); + Thread.sleep(time*1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Thread.currentThread().setName("OOOOOOOOO"); + MessageUtil.sendHeartBeat(session); + } + }).start(); +// MessageUtil.sendHeartBeat(session); + } + + private int checkAndRefresh(ISession session, PacketNetData packetNetData) { + int myToken = 0; + + if (packetNetData.getMsgId()== MessageTypeProto.MessageType.LOGIN_REQUEST_VALUE){ + + }else if (packetNetData.getMsgId()== MessageTypeProto.MessageType.LOGIN_REQUEST_VALUE){ + + }else { + + } + if (myToken != packetNetData.getToken()){ + return 1; + } + session.setUserLoginTime(System.currentTimeMillis()/1000); + session.setToken(myToken); + return 0; + } @Override diff --git a/serverlogic/src/main/java/com/ljsd/jieling/thread/ThreadManager.java b/serverlogic/src/main/java/com/ljsd/jieling/thread/ThreadManager.java new file mode 100644 index 000000000..bbeec9794 --- /dev/null +++ b/serverlogic/src/main/java/com/ljsd/jieling/thread/ThreadManager.java @@ -0,0 +1,66 @@ +package com.ljsd.jieling.thread; + +import com.ljsd.jieling.thread.task.TestTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ConfigurableApplicationContext; + +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +public class ThreadManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(ThreadManager.class); + + + private TestTask testTask; + + + private ScheduledThreadPoolExecutor scheduledExecutor; //管理task + + public void init(ConfigurableApplicationContext configurableApplicationContext) { + + testTask = configurableApplicationContext.getBean(TestTask.class); + + go(); + } + + + static class ScheduleThreadFactory implements ThreadFactory { + + final ThreadGroup group; + + final AtomicInteger threadNumber = new AtomicInteger(1); + + final String namePrefix; + + ScheduleThreadFactory() { + SecurityManager s = System.getSecurityManager(); + group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); + namePrefix = "ScheduleThreadPool" + "-thread-"; + } + + public Thread newThread(Runnable r) { + Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); + if (t.isDaemon()) + t.setDaemon(false); + if (t.getPriority() != Thread.NORM_PRIORITY) + t.setPriority(Thread.NORM_PRIORITY); + return t; + } + } + + + public void go() { + + scheduledExecutor = new ScheduledThreadPoolExecutor(8, new ScheduleThreadFactory()); + + // testTask 已秒为单位 延迟10s, 间隔30s为周期执行 + scheduledExecutor.scheduleAtFixedRate(testTask, 10, 30, TimeUnit.SECONDS); + + LOGGER.info("All Task running ..."); + } + +} diff --git a/serverlogic/src/main/java/com/ljsd/jieling/thread/task/TestTask.java b/serverlogic/src/main/java/com/ljsd/jieling/thread/task/TestTask.java new file mode 100644 index 000000000..8e8f517b4 --- /dev/null +++ b/serverlogic/src/main/java/com/ljsd/jieling/thread/task/TestTask.java @@ -0,0 +1,24 @@ +package com.ljsd.jieling.thread.task; + +import com.ljsd.jieling.db.redis.RedisUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class TestTask implements Runnable { + + private static final Logger LOGGER = LoggerFactory.getLogger(TestTask.class); + + + @Override + public void run() { + doLogic(); + } + + private void doLogic() { + long str = RedisUtil.getInstence().incr("TestTask",1L); + LOGGER.info("--> RedisUtil.incr : str = "+str); + LOGGER.info("TestTask ... "); + } +} diff --git a/serverlogic/src/main/java/com/ljsd/jieling/util/MessageUtil.java b/serverlogic/src/main/java/com/ljsd/jieling/util/MessageUtil.java index 18d05f4a3..d4420b25e 100644 --- a/serverlogic/src/main/java/com/ljsd/jieling/util/MessageUtil.java +++ b/serverlogic/src/main/java/com/ljsd/jieling/util/MessageUtil.java @@ -38,9 +38,7 @@ public class MessageUtil { if (backMessage.length != 0) { System.arraycopy(backMessage, 0, bytes, pos, backMessage.length); } - int[] secretKey = Tea.KEY; - return Tea.encrypt2(bytes, secretKey); } @@ -69,6 +67,11 @@ public class MessageUtil { session.writeAndFlush(byteBuf); } + public static void sendErrorCode(ISession session) { + + + } + // public static void sendErrorResponse(Msg msg, GeneratedMessage error_message, int msgId) throws Exception { // String protoEntity = Base64.getEncoder().encodeToString(error_message.toByteArray()); // BaseGlobal.redisApp.hset(RedisKey.RESPONSE, String.valueOf(msg.getUid()), String.valueOf(Math.abs(msg.getIndex())), new ProtoEntity(msgId, protoEntity), -1); diff --git a/serverlogic/src/main/resources/application.properties b/serverlogic/src/main/resources/application.properties index c2fd45549..0a1c9a236 100644 --- a/serverlogic/src/main/resources/application.properties +++ b/serverlogic/src/main/resources/application.properties @@ -1,5 +1,6 @@ #server info server.id = 10180 +server.openTime = 20190101000101 # redis config @@ -34,7 +35,7 @@ mongodb.options.connectTimeout = 1000 mongodb.options.socketTimeout = 0 mongodb.options.threadsAllowedToBlockForConnectionMultiplier = 20 mongodb.options.connectionsPerHost = 256 -mongodb.options.minConnectionsPerHost = 100 +mongodb.options.minConnectionsPerHost = 5 mongodb.options.maxConnectionIdleTime = 1000