package com.ctrip.hermes.core.cmessaging; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.unidal.lookup.annotation.Inject; import org.unidal.lookup.annotation.Named; import org.unidal.tuple.Pair; import com.alibaba.fastjson.JSON; import com.ctrip.hermes.cmessaging.entity.Cmessaging; import com.ctrip.hermes.cmessaging.entity.Consume; import com.ctrip.hermes.cmessaging.entity.ConsumeGroup; import com.ctrip.hermes.cmessaging.entity.Exchange; import com.ctrip.hermes.cmessaging.entity.Node; import com.ctrip.hermes.cmessaging.entity.Produce; import com.ctrip.hermes.cmessaging.entity.ProduceGroup; import com.ctrip.hermes.core.config.CoreConfig; import com.ctrip.hermes.core.meta.internal.MetaManager; import com.ctrip.hermes.core.utils.HermesThreadFactory; @Named(type = CMessagingConfigService.class) public class DefaultCMessagingConfigService implements CMessagingConfigService, Initializable { private static Logger log = LoggerFactory.getLogger(DefaultCMessagingConfigService.class); @Inject private MetaManager m_metaManager; @Inject private CoreConfig m_coreConfig; private AtomicReference<Cmessaging> m_cmsgConfigCache = new AtomicReference<>(); private Map<String, String> m_restParams = new HashMap<String, String>(1); private Exchange findExchange(String exchangeName) { Exchange exchange = m_cmsgConfigCache.get().findExchange(exchangeName); return exchange; } @Override public String getTopic(String exchangeName) { Exchange exchange = findExchange(exchangeName); String result = null; if (exchange != null) { result = exchange.getHermesTopic(); } return result; } @Override public String getGroupId(String exchangeName, String idAndQueueName) { Exchange exchange = findExchange(exchangeName); String result = null; if (exchange != null) { ConsumeGroup group = exchange.getConsume().findConsumeGroup(idAndQueueName); if (group != null) { result = group.getHermesConsumerGroup(); } } return result; } @Override public boolean isHermesProducerEnabled(String exchangeName, String identifier, String ip) { Exchange exchange = findExchange(exchangeName); if (exchange == null || exchange.getProduce() == null) { return false; } else { if (Produce.GRAY.equalsIgnoreCase(exchange.getProduce().getState())) { ProduceGroup group = exchange.getProduce().findProduceGroup(identifier); if (group == null) { return false; } else { if (Produce.GRAY.equalsIgnoreCase(group.getState())) { return group.findNode(ip) != null; } else { return nonGrayProduceStateToBoolean(group.getState()); } } } else { return nonGrayProduceStateToBoolean(exchange.getProduce().getState()); } } } private boolean nonGrayProduceStateToBoolean(String state) { switch (state) { case Produce.CLOSE: return false; case Produce.OPEN: return true; default: throw new RuntimeException(String.format("Unknow state (%s)", state)); } } @Override public int getConsumerType(String exchangeName, String identifier, String ip) { Exchange exchange = findExchange(exchangeName); if (exchange == null || exchange.getConsume() == null) { return CMessagingConfigService.CONSUME_FROM_CMESSAGING; } else { if (Consume.GRAY.equalsIgnoreCase(exchange.getConsume().getState())) { ConsumeGroup group = exchange.getConsume().findConsumeGroup(identifier); if (group == null) { return CMessagingConfigService.CONSUME_FROM_CMESSAGING; } else { if (Consume.GRAY.equalsIgnoreCase(group.getState())) { Node node = group.findNode(ip); if (node == null) { return CMessagingConfigService.CONSUME_FROM_CMESSAGING; } else { return CMessagingConfigService.CONSUME_FROM_BOTH; } } else { return nonGrayConsumeStateToInt(group.getState()); } } } else { return nonGrayConsumeStateToInt(exchange.getConsume().getState()); } } } private int nonGrayConsumeStateToInt(String state) { switch (state) { case Consume.CLOSE: return CMessagingConfigService.CONSUME_FROM_CMESSAGING; case Consume.BOTH_OPEN: return CMessagingConfigService.CONSUME_FROM_BOTH; case Consume.HERMES_ONLY: return CMessagingConfigService.CONSUME_FROM_HERMES; default: throw new RuntimeException(String.format("Unknow state (%s)", state)); } } @Override public void initialize() throws InitializationException { boolean initSuccess = false; try { initSuccess = updateConfig(); } catch (Exception e) { throw new InitializationException("Can not fetch cmessaging config from any meta server", e); } if (!initSuccess) { throw new InitializationException("Can not fetch cmessaging config from any meta server"); } HermesThreadFactory.create("CMessagingConfigUpdater", true).newThread(new ConfigUpdateTask()).start(); } private boolean updateConfig() { boolean success = false; if (m_cmsgConfigCache.get() != null) { m_restParams.put("version", Long.toString(m_cmsgConfigCache.get().getVersion())); } Pair<Integer, String> codeAndRes = m_metaManager.getMetaProxy().getRequestToMetaServer("/cmessage/config", m_restParams); if (codeAndRes != null) { int code = codeAndRes.getKey(); if (code == 200) { try { m_cmsgConfigCache.set(JSON.parseObject(codeAndRes.getValue(), Cmessaging.class)); success = true; } catch (Exception e) { log.error("Wrong format of cmessaging config " + codeAndRes.getValue(), e); } } else if (code == 304) { success = true; } } return success; } private class ConfigUpdateTask implements Runnable { @Override public void run() { while (true) { try { Thread.sleep(m_coreConfig.getCMessagingConfigUpdateInterval()); updateConfig(); } catch (Exception e) { log.warn("Error update cmessaging config", e); } } } } }