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.common.util.ErrorsUtil; import com.snowcattle.game.common.util.ExecutorUtil; import com.snowcattle.game.logic.net.NetMessageProcessLogic; import com.snowcattle.game.manager.LocalMananger; import com.snowcattle.game.service.net.MessageAttributeEnum; import com.snowcattle.game.common.ThreadNameFactory; import com.snowcattle.game.service.net.message.AbstractNetMessage; import com.snowcattle.game.service.net.message.AbstractNetProtoBufMessage; import com.snowcattle.game.service.net.session.NettyUdpSession; import org.slf4j.Logger; import java.util.LinkedList; import java.util.List; import java.util.concurrent.*; /** * Created by jiangwenping on 17/2/13. */ public class QueueMessageExecutorProcessor implements IMessageProcessor { 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 QueueMessageExecutorProcessor() { this(false, 1); } @SuppressWarnings("unchecked") public QueueMessageExecutorProcessor(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); } } } /** * 处理具体的消息,每个消息有自己的参数和来源,如果在处理消息的过程中发生异常,则马上将此消息的发送者断掉 * * @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; NettyUdpSession clientSesion = (NettyUdpSession) abstractNetProtoBufMessage.getAttribute(MessageAttributeEnum.DISPATCH_SESSION); //所有的session已经强制绑定了,这里不需要再判定空了 if(logger.isDebugEnabled()) { logger.debug("processor session" + clientSesion.getPlayerId() + " process message" + abstractNetProtoBufMessage.toAllInfoString()); } NetMessageProcessLogic netMessageProcessLogic = LocalMananger.getInstance().getLocalSpringBeanManager().getNetMessageProcessLogic(); netMessageProcessLogic.processMessage(msg, clientSesion); } 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); } } } } }