/* * Copyright 2008-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.hasor.registry.server.pushing; import net.hasor.core.AppContext; import net.hasor.core.Init; import net.hasor.core.Inject; import net.hasor.core.Singleton; import net.hasor.registry.server.manager.ServerSettings; import net.hasor.registry.trace.TraceUtil; import net.hasor.registry.server.domain.LogUtils; import net.hasor.rsf.InterAddress; import net.hasor.rsf.RsfContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; /** * 推送服务触发器 * @version : 2016年3月1日 * @author 赵永春(zyc@hasor.net) */ @Singleton public class PushQueue implements Runnable { protected Logger logger = LoggerFactory.getLogger(getClass()); private LinkedBlockingQueue<PushEvent> dataQueue; private ArrayList<Thread> threadPushQueue; private Map<RsfCenterEventEnum, PushProcessor> processorMapping; @Inject private RsfContext rsfContext; @Inject private ServerSettings rsfCenterCfg; // @Init public void init() { AppContext app = this.rsfContext.getAppContext(); this.processorMapping = new HashMap<RsfCenterEventEnum, PushProcessor>(); for (RsfCenterEventEnum eventType : RsfCenterEventEnum.values()) { PushProcessor processor = app.getInstance(eventType.getProcessorType()); this.processorMapping.put(eventType, processor); logger.info("pushQueue processor mapping {} -> {}", eventType.forCenterEvent(), eventType.getProcessorType()); } // this.dataQueue = new LinkedBlockingQueue<PushEvent>(); this.threadPushQueue = new ArrayList<Thread>(); int threadSize = rsfCenterCfg.getThreadSize(); for (int i = 1; i <= threadSize; i++) { Thread pushQueue = new Thread(this); pushQueue.setDaemon(true); pushQueue.setName("Rsf-Center-PushQueue-" + i); pushQueue.setContextClassLoader(this.rsfContext.getClassLoader()); pushQueue.start(); this.threadPushQueue.add(pushQueue); } logger.info("PushQueue Thread start."); } public void run() { while (true) { try { PushEvent pushEvent = null; while ((pushEvent = this.dataQueue.take()) != null) { doPush(pushEvent); } } catch (Throwable e) { logger.error(LogUtils.create("ERROR_300_00004")// .addLog("traceID", TraceUtil.getTraceID())// .logException(e).toJson()); } } } // // - 立刻执行消息推送,返回推送失败的地址列表。 private List<InterAddress> doPush(PushEvent pushEvent) { PushProcessor pushProcessor = this.processorMapping.get(pushEvent.getPushEventType()); if (pushProcessor != null) { return pushProcessor.doProcessor(pushEvent); } else { logger.error(LogUtils.create("ERROR_300_00005")// .addLog("traceID", TraceUtil.getTraceID())// .addLog("pushEventType", pushEvent.getPushEventType().name())// .toJson()); } return pushEvent.getTarget(); } // - 将消息推送交给推送线程,执行异步推送。 public boolean doPushEvent(PushEvent eventData) { if (this.dataQueue.size() > this.rsfCenterCfg.getQueueMaxSize()) { try { Thread.sleep(this.rsfCenterCfg.getSleepTime()); } catch (Exception e) { logger.error(LogUtils.create("ERROR_300_00004")// .addLog("traceID", TraceUtil.getTraceID())// .logException(e).toJson()); } if (this.dataQueue.size() > this.rsfCenterCfg.getQueueMaxSize()) { return false;//资源还是紧张,返回 失败 } } // this.dataQueue.offer(eventData);//资源不在紧张,加入到队列中。 return true; } }