package com.snowcattle.game.service.net.process; import com.snowcattle.game.common.config.GameServerDiffConfig; import com.snowcattle.game.common.constant.CommonErrorLogInfo; import com.snowcattle.game.common.constant.GlobalConstants; import com.snowcattle.game.common.constant.Loggers; import com.snowcattle.game.manager.LocalMananger; import com.snowcattle.game.service.net.message.AbstractNetMessage; import com.snowcattle.game.common.util.ExecutorUtil; import com.snowcattle.game.logic.net.NetMessageTcpDispatchLogic; import com.snowcattle.game.common.ThreadNameFactory; import org.slf4j.Logger; import java.util.LinkedList; import java.util.List; import java.util.concurrent.*; /** * Created by jiangwenping on 17/2/20. * 默认不开启worker线程 */ public class QueueTcpMessageExecutorProcessor implements ITcpMessageProcessor{ public static final Logger logger = Loggers.serverStatusStatistics; /** 消息队列 * */ protected final BlockingQueue<AbstractNetMessage> queue; /** 消息处理线程停止时剩余的还未处理的消息 **/ private volatile List<AbstractNetMessage> leftQueue; /** 消息处理线程池 */ private volatile ExecutorService executorService; /** 线程池的线程个数 */ private int excecutorCoreSize; /** 是否停止 */ private volatile boolean stop = false; // /** 处理的消息总数 */ // public long statisticsMessageCount = 0; private final boolean processLeft; @SuppressWarnings("unchecked") public QueueTcpMessageExecutorProcessor() { this(false, 0); } @SuppressWarnings("unchecked") public QueueTcpMessageExecutorProcessor(boolean processLeft, int executorCoreSize) { queue = new LinkedBlockingQueue<AbstractNetMessage>(); this.processLeft = processLeft; this.excecutorCoreSize = executorCoreSize; } /* * (non-Javadoc) * * @see com.mop.lzr.core.server.IMessageProcessor#put(com.mop.lzr.core.msg. * IMessage) */ public void put(AbstractNetMessage msg) { try { queue.put(msg); if (logger.isDebugEnabled()) { logger.debug("put queue size:" + queue.size()); } } catch (InterruptedException e) { if (logger.isErrorEnabled()) { logger.error(CommonErrorLogInfo.THRAD_ERR_INTERRUPTED, e); } } } @Override public void directPutTcpMessage(AbstractNetMessage msg) { try { NetMessageTcpDispatchLogic netMessageTcpDispatchLogic = LocalMananger.getInstance().getLocalSpringBeanManager().getNetMessageTcpDispatchLogic(); netMessageTcpDispatchLogic.dispatchTcpMessage(msg, this); } catch (Exception e) { if (logger.isErrorEnabled()) { logger.error(CommonErrorLogInfo.THRAD_ERR_INTERRUPTED, e); } } } /** * 处理具体的消息,每个消息有自己的参数和来源,如果在处理消息的过程中发生异常,则马上将此消息的发送者断掉 * * @param msg */ @SuppressWarnings("unchecked") public void process(AbstractNetMessage msg) { // if (msg == null) { // if (logger.isWarnEnabled()) { // logger.warn("[#CORE.QueueMessageExecutorProcessor.process] [" // + CommonErrorLogInfo.MSG_PRO_ERR_NULL_MSG + "]"); // } // return; // } // long begin = 0; // if (logger.isInfoEnabled()) { // begin = System.nanoTime(); // } // this.statisticsMessageCount++; // try { // AbstractNetProtoBufMessage abstractNetProtoBufMessage = (AbstractNetProtoBufMessage) msg; // NettyTcpSession clientSesion = (NettyTcpSession) abstractNetProtoBufMessage.getAttribute(MessageAttributeEnum.DISPATCH_SESSION); // if(clientSesion != null){ // logger.debug("processor session" + clientSesion.getPlayerId() + " process message" + msg.getNetMessageHead().getCmd()); // clientSesion.getNetProtoBufMessageProcess().addNetMessage(abstractNetProtoBufMessage); // }else{ // //// NetTcpSessionLoopUpService netTcpSessionLoopUpService = LocalMananger.getInstance().get(NetTcpSessionLoopUpService.class); //// NettySession clientSesion = netTcpSessionLoopUpService.lookup(sessionId); //// if(clientSesion != null){ //// logger.debug("processor session" + clientSesion.getPlayerId() + " process message" + msg.getCommandId()); //// clientSesion.addGameMessage(msg); //// //// }else{ //// logger.debug("session is closed, the message is unDispatch"); //// } // } // // } catch (Exception e) { // if (logger.isErrorEnabled()) { // logger.error(ErrorsUtil.error("Error", // "#.QueueMessageExecutorProcessor.process", "param"), e); // } // // } finally { // if (logger.isInfoEnabled()) { // // 特例,统计时间跨度 // long time = (System.nanoTime() - begin) / (1000 * 1000); // if (time > 1) { // logger.info("#CORE.MSG.PROCESS.DISPATCH_STATICS disptach Message id:" // + msg.getNetMessageHead().getCmd() + " Time:" // + time + "ms" + " Total:" // + this.statisticsMessageCount); // } // } // } } /** * 开始消息处理 */ public synchronized void start() { if (this.executorService != null) { throw new IllegalStateException( "The executorSerive has not been stopped."); } stop = false; ThreadNameFactory factory = new ThreadNameFactory(GlobalConstants.Thread.GAME_MESSAGE_QUEUE_EXCUTE); this.executorService = Executors .newFixedThreadPool(this.excecutorCoreSize, factory); GameServerDiffConfig gameServerDiffConfig = LocalMananger.getInstance().getLocalSpringServiceManager().getGameServerConfigService().getGameServerDiffConfig(); for (int i = 0; i < this.excecutorCoreSize; i++) { this.executorService.execute(new Worker()); } logger.info("Message processor executorService started [" + this.executorService + " with " + this.excecutorCoreSize + " threads ]"); } /** * 停止消息处理 */ public synchronized void stop() { logger.info("Message processor executor " + this + " stopping ..."); this.stop = true; if (this.executorService != null) { ExecutorUtil.shutdownAndAwaitTermination(this.executorService, 50, TimeUnit.MILLISECONDS); this.executorService = null; } logger.info("Message processor executor " + this + " stopped"); if (this.processLeft) { // 将未处理的消息放入到leftQueue中,以备后续处理 this.leftQueue = new LinkedList<AbstractNetMessage>(); while (true) { AbstractNetMessage _msg = this.queue.poll(); if (_msg != null) { this.leftQueue.add(_msg); } else { break; } } } this.queue.clear(); } /** * 达到5000上限时认为满了 */ public boolean isFull() { return this.queue.size() > 5000; } /** * 取得消息处理器停止后的遗留的消息 * * @return the leftQueue */ public List<AbstractNetMessage> getLeftQueue() { return leftQueue; } /** * 重置 */ public void resetLeftQueue() { this.leftQueue = null; } private final class Worker implements Runnable { @Override public void run() { while (!stop) { try { process(queue.take()); if (logger.isDebugEnabled()) { logger.debug("run queue size:" + queue.size()); } } catch (InterruptedException e) { if (logger.isWarnEnabled()) { logger .warn("[#CORE.QueueMessageExecutorProcessor.run] [Stop process]"); } Thread.currentThread().interrupt(); break; } catch (Exception e) { e.printStackTrace(); logger.error(CommonErrorLogInfo.MSG_PRO_ERR_EXP, e); } } } } }