在前文中我们讲过PTP和PUB/SUB模式实例,今天我们来看一下ActiveMQ是如何生产消息的
实例主要生产者代码片段:
ConnectionFactory :连接工厂,JMS 用它创建连接
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user,password,url);
Connection :JMS 客户端到JMS Provider 的连接
Connection connection = connectionFactory.createConnection();
Connection 启动
connection.start();
System.out.println("Connection is start...");
Session: 一个发送或接收消息的线程
Session session = connection.createSession(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);
Queue :消息的目的地;消息发送给谁.
Queue destination = session.createQueue(qname);
MessageProducer:消息发送者
MessageProducer producer = session.createProducer(destination);
设置持久化,此处学习,实际根据项目决定
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
构造消息,此处写死,项目就是参数,或者方法获取
sendMessage(session, producer); session.commit(); connection.close();
我们依次来看上面的连接工厂,连接,会话,消息队列和订阅主题,生产者及发送消息
1.连接工厂
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user,password,url); //ActiveMQConnectionFactory public class ActiveMQConnectionFactory extends JNDIBaseStorable implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory, StatsCapable, Cloneable { private static final Logger LOG; private static final String DEFAULT_BROKER_HOST;//默认ip private static final int DEFAULT_BROKER_PORT;//默认端口 public static final String DEFAULT_BROKER_BIND_URL;//broker默认绑定地址 public static final String DEFAULT_BROKER_URL;//默认broker URL public static final String DEFAULT_USER = null;//默认用户 public static final String DEFAULT_PASSWORD = null;//默认密码 public static final int DEFAULT_PRODUCER_WINDOW_SIZE = 0;//默认生产者窗口大小 protected URI brokerURL;//broker URL protected String userName;//用户名 protected String password;//密码 protected String clientID;//客户端id protected boolean dispatchAsync; protected boolean alwaysSessionAsync; JMSStatsImpl factoryStats; private IdGenerator clientIdGenerator; private String clientIDPrefix; private IdGenerator connectionIdGenerator; private String connectionIDPrefix;//连接id前缀 private ActiveMQPrefetchPolicy prefetchPolicy; private RedeliveryPolicyMap redeliveryPolicyMap; private BlobTransferPolicy blobTransferPolicy; private MessageTransformer transformer; private boolean disableTimeStampsByDefault; private boolean optimizedMessageDispatch; private long optimizeAcknowledgeTimeOut; private long optimizedAckScheduledAckInterval; private boolean copyMessageOnSend;//是否拷贝消息 private boolean useCompression;//是否压缩消息 private boolean objectMessageSerializationDefered; private boolean useAsyncSend;//是否异步发送消息 private boolean optimizeAcknowledge; private int closeTimeout;//关闭连接超时时间 private boolean useRetroactiveConsumer; private boolean exclusiveConsumer; private boolean nestedMapAndListEnabled; private boolean alwaysSyncSend;//是否总是异步发送 private boolean watchTopicAdvisories; private int producerWindowSize;//生产窗口大小 private long warnAboutUnstartedConnectionTimeout; private int sendTimeout; private boolean sendAcksAsync;//是否发送异步ACK private TransportListener transportListener;// transport监听器 private ExceptionListener exceptionListener; private int auditDepth; private int auditMaximumProducerNumber; private boolean useDedicatedTaskRunner; //当集群master宕机,重新选举master时,消费者等待重新消费的时间 private long consumerFailoverRedeliveryWaitPeriod; private boolean checkForDuplicates; private ClientInternalExceptionListener clientInternalExceptionListener;//消费内部监听器 private boolean messagePrioritySupported;//是否支持消息优先级 private boolean transactedIndividualAck; private boolean nonBlockingRedelivery;//是否非阻塞传输 private int maxThreadPoolSize;//最大线程池 private TaskRunnerFactory sessionTaskRunner;//session任务工厂 private RejectedExecutionHandler rejectedTaskHandler; protected int xaAckMode; private boolean rmIdFromConnectionId; private boolean consumerExpiryCheckEnabled;//是否检查消费者超时 static { LOG = LoggerFactory.getLogger(org/apache/activemq/ActiveMQConnectionFactory); String host = null; String port = null; try { host = (String)AccessController.doPrivileged(new PrivilegedAction() { public String run() { String result = System.getProperty("org.apache.activemq.AMQ_HOST"); result = result != null && !result.isEmpty() ? result : System.getProperty("AMQ_HOST", "localhost"); return result; } public volatile Object run() { return run(); } }); port = (String)AccessController.doPrivileged(new PrivilegedAction() { public String run() { String result = System.getProperty("org.apache.activemq.AMQ_PORT"); result = result != null && !result.isEmpty() ? result : System.getProperty("AMQ_PORT", "61616"); return result; } public volatile Object run() { return run(); } }); } catch(Throwable e) { LOG.debug("Failed to look up System properties for host and port", e); } //默认ip为localhost,端口为61616 host = host != null && !host.isEmpty() ? host : "localhost"; port = port != null && !port.isEmpty() ? port : "61616"; DEFAULT_BROKER_HOST = host; DEFAULT_BROKER_PORT = Integer.parseInt(port); String defaultURL = (new StringBuilder()).append("tcp://").append(DEFAULT_BROKER_HOST).append(":").append(DEFAULT_BROKER_PORT).toString(); String bindURL = null; try { bindURL = (String)AccessController.doPrivileged(new PrivilegedAction(defaultURL) { public String run() { String result = System.getProperty("org.apache.activemq.BROKER_BIND_URL"); result = result != null && !result.isEmpty() ? result : System.getProperty("BROKER_BIND_URL", defaultURL); return result; } public volatile Object run() { return run(); } final String val$defaultURL; { defaultURL = s; super(); } }); } catch(Throwable e) { LOG.debug("Failed to look up System properties for host and port", e); } //默认url为tcp://localhost8:61616 bindURL = bindURL != null && !bindURL.isEmpty() ? bindURL : defaultURL; DEFAULT_BROKER_BIND_URL = bindURL; //默认broke url为failover://tcp://localhost8:61616 DEFAULT_BROKER_URL = (new StringBuilder()).append("failover://").append(DEFAULT_BROKER_BIND_URL).toString(); } }
从ActiveMQConnectionFactory属性主要为broker url,用户密码,是否压缩、异步发送消息、
支持消息优先级、非阻塞传输,最大线程数,生产窗口大小等属性;
静态语句块,从系统获取url,port,broker url,如果系统中不存在相关属性,赋予默认值。
再来看ActiveMQConnectionFactory构造:
public ActiveMQConnectionFactory(String userName, String password, String brokerURL) { dispatchAsync = true;//默认异步分发 alwaysSessionAsync = true;//异步发送消息 factoryStats = new JMSStatsImpl(); prefetchPolicy = new ActiveMQPrefetchPolicy(); redeliveryPolicyMap = new RedeliveryPolicyMap(); redeliveryPolicyMap.setDefaultEntry(new RedeliveryPolicy()); blobTransferPolicy = new BlobTransferPolicy(); optimizedMessageDispatch = true; optimizeAcknowledgeTimeOut = 300L; optimizedAckScheduledAckInterval = 0L; copyMessageOnSend = true; closeTimeout = 15000;//关闭超时时间 nestedMapAndListEnabled = true; watchTopicAdvisories = true; producerWindowSize = 0;//消息窗口大小 warnAboutUnstartedConnectionTimeout = 500L; sendTimeout = 0;//发送超时时间 sendAcksAsync = true;//异步发送ACK auditDepth = 2048; auditMaximumProducerNumber = 64; consumerFailoverRedeliveryWaitPeriod = 0L; checkForDuplicates = true; messagePrioritySupported = false;//默认不支持消息优先级 transactedIndividualAck = false; nonBlockingRedelivery = false;//默认为阻塞模式 maxThreadPoolSize = ActiveMQConnection.DEFAULT_THREAD_POOL_SIZE;//最大线程池大小 rejectedTaskHandler = null; xaAckMode = -1; rmIdFromConnectionId = false; consumerExpiryCheckEnabled = true; //设置用户密码,broker url setUserName(userName); setPassword(password); setBrokerURL(brokerURL); }
从构造可以看出,主要初始化为broker url,用户密码,是否压缩、异步发送消息、
支持消息优先级、非阻塞传输,最大线程数,生产窗口大小等属性;
下面来看一下连接的获取
2.连接
Connection connection = connectionFactory.createConnection(); //ActiveMQConnectionFactory public Connection createConnection() throws JMSException { return createActiveMQConnection(); } protected ActiveMQConnection createActiveMQConnection() throws JMSException { return createActiveMQConnection(userName, password); } //最终ActiveMQ创建连接方法,返回的为ActiveMQConnection protected ActiveMQConnection createActiveMQConnection(String userName, String password) throws JMSException { ActiveMQConnection connection; if(brokerURL == null) throw new ConfigurationException("brokerURL not set."); connection = null; //创建transport Transport transport = createTransport(); //创建连接 connection = createActiveMQConnection(transport, factoryStats); //设置连接用户密码 connection.setUserName(userName); connection.setPassword(password); //配置连接 configureConnection(connection); //启动transport transport.start(); if(clientID != null) connection.setDefaultClientID(clientID); return connection; catch(Throwable throwable1) { } throw JMSExceptionSupport.create((new StringBuilder()).append("Could not connect to broker URL: ").append(brokerURL).append(". Reason: ").append(e).toString(), e); }
我们分别来看以上几点
a.创建transport
Transport transport = createTransport();
protected Transport createTransport() throws JMSException { //由TransportFactory工厂连接brokerURL创建Transport return TransportFactory.connect(brokerURL); Exception e; e; throw JMSExceptionSupport.create((new StringBuilder()).append("Could not create Transport. Reason: ").append(e).toString(), e); }
再看TransportFactory
//TransportFactory
public abstract class TransportFactory { private static final FactoryFinder TRANSPORT_FACTORY_FINDER = new FactoryFinder("META-INF/services/org/apache/activemq/transport/"); private static final FactoryFinder WIREFORMAT_FACTORY_FINDER = new FactoryFinder("META-INF/services/org/apache/activemq/wireformat/"); //ConcurrentHashMap,broker uri协议与TransportFactory的映射 private static final ConcurrentMap TRANSPORT_FACTORYS = new ConcurrentHashMap(); private static final String WRITE_TIMEOUT_FILTER = "soWriteTimeout"; private static final String THREAD_NAME_FILTER = "threadName"; public static Transport connect(URI location) throws Exception { //跟Broker URI 获取TransportFactory TransportFactory tf = findTransportFactory(location); //获取连接 return tf.doConnect(location); } }
//从TRANSPORT_FACTORYS获取borkerURI对应的TransportFactory,没有则,
TRANSPORT_FACTORY_FINDER根据brokerURI创建对应的TransportFactory的实例放入TRANSPORT_FACTORYS中
public static TransportFactory findTransportFactory(URI location) throws IOException { String scheme = location.getScheme(); if(scheme == null) throw new IOException((new StringBuilder()).append("Transport not scheme specified: [").append(location).append("]").toString()); TransportFactory tf = (TransportFactory)TRANSPORT_FACTORYS.get(scheme); if(tf == null) try { //TRANSPORT_FACTORY_FINDER根据协议名创建TransportFactory实例 tf = (TransportFactory)TRANSPORT_FACTORY_FINDER.newInstance(scheme); TRANSPORT_FACTORYS.put(scheme, tf); } catch(Throwable e) { throw IOExceptionSupport.create((new StringBuilder()).append("Transport scheme NOT recognized: [").append(scheme).append("]").toString(), e); } return tf; }
从FactoryFinder,可以看到有一个META-INF/services/org/apache/activemq/transport/路径
private static final FactoryFinder TRANSPORT_FACTORY_FINDER = new FactoryFinder("META-INF/services/org/apache/activemq/transport/");
找到这个路径,可以看到有一些文本文件http,nio,amqp,failover,ssl,tcp,vm等;
tcp这个就是我们找到,打开文件如下:
class=org.apache.activemq.transport.tcp.TcpTransportFactory
TcpTransportFactory看到这个想到了什么,就是我们要找的,FactoryFinder就是根据
BrokerURI的协议来找META-INF/services/org/apache/activemq/transport/下的对应文件,
然后加载class属性对应的类,由于我们的broker地址,为tcp://192.168.126.128:61616,所以协议为TCP
对应的为TcpTransportFactory,好了到这里TransportFactory工厂创建完毕。这里只是猜测
//回看一下FactoryFinder
public class FactoryFinder { private static ObjectFactory objectFactory = new StandaloneObjectFactory(); private final String path; //根据brokerUri协议创建TransportFactory实例 public Object newInstance(String key) throws IllegalAccessException, InstantiationException, IOException, ClassNotFoundException { return objectFactory.create((new StringBuilder()).append(path).append(key).toString()); } protected static class StandaloneObjectFactory implements ObjectFactory { //ConcurrentHashMapfinal ConcurrentMap classMap = new ConcurrentHashMap(); //根据broker URI协议创建TransportFactory public Object create(String path) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IOException { Class clazz = (Class)classMap.get(path); if(clazz == null) { clazz = loadClass(loadProperties(path)); classMap.put(path, clazz); } return clazz.newInstance(); } //加载class对应的TransportFactory public static Class loadClass(Properties properties) throws ClassNotFoundException, IOException { String className = properties.getProperty("class"); if(className == null) throw new IOException("Expected property is missing: class"); Class clazz = null; ClassLoader loader = Thread.currentThread().getContextClassLoader(); if(loader != null) try { clazz = loader.loadClass(className); } catch(ClassNotFoundException classnotfoundexception) { } if(clazz == null) clazz = org/apache/activemq/util/FactoryFinder.getClassLoader().loadClass(className); return clazz; } //加载属性文件 public static Properties loadProperties(String uri) throws IOException { InputStream in; BufferedInputStream reader; ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if(classLoader == null) classLoader = org/apache/activemq/util/FactoryFinder$StandaloneObjectFactory.getClassLoader(); in = classLoader.getResourceAsStream(uri); if(in == null) { in = org/apache/activemq/util/FactoryFinder.getClassLoader().getResourceAsStream(uri); if(in == null) throw new IOException((new StringBuilder()).append("Could not find factory class for resource: ").append(uri).toString()); } reader = null; Properties properties1; reader = new BufferedInputStream(in); Properties properties = new Properties(); properties.load(reader); properties1 = properties; } } }
再看从TransportFactory工厂获取连接:
//获取连接
return tf.doConnect(location);
TransportFactory获取连接 public Transport doConnect(URI location) throws Exception { Transport rc; Map options = new HashMap(URISupport.parseParameters(location)); if(!options.containsKey("wireFormat.host")) options.put("wireFormat.host", location.getHost()); WireFormat wf = createWireFormat(options); 创建transport Transport transport = createTransport(location, wf); 配置transport rc = configure(transport, wf, options); return rc; }
//待父类扩展
protected Transport createTransport(URI location, WireFormat wf) throws MalformedURLException, UnknownHostException, IOException { throw new IOException("createTransport() method not implemented!"); }
再看其父类
public class TcpTransportFactory extends TransportFactory { protected Transport createTransport(URI location, WireFormat wf) throws UnknownHostException, IOException { URI localLocation = null; String path = location.getPath(); if(path != null && path.length() > 0) { int localPortIndex = path.indexOf(':'); try { Integer.parseInt(path.substring(localPortIndex + 1, path.length())); String localString = (new StringBuilder()).append(location.getScheme()).append(":/").append(path).toString(); localLocation = new URI(localString); } } //创建socket的工场 SocketFactory socketFactory = createSocketFactory(); //创建TcpTransport return createTcpTransport(wf, socketFactory, location, localLocation); } }
//创建socket的工场
SocketFactory socketFactory = createSocketFactory(); protected SocketFactory createSocketFactory() throws IOException { return SocketFactory.getDefault(); } //DefaultSocketFactory public abstract class SocketFactory { public static SocketFactory getDefault() { synchronized(javax/net/SocketFactory) { if(theFactory == null) theFactory = new DefaultSocketFactory(); } return theFactory; }
//创建TcpTransport,socketFactory为DefaultSocketFactory
return createTcpTransport(wf, socketFactory, location, localLocation); protected TcpTransport createTcpTransport(WireFormat wf, SocketFactory socketFactory, URI location, URI localLocation) throws UnknownHostException, IOException { //返回的是TcpTransport return new TcpTransport(wf, socketFactory, location, localLocation); } //TcpTransport public class TcpTransport extends TransportThreadSupport implements Transport, Service, Runnable { protected final URI remoteLocation;//远程URI protected final URI localLocation;//本地URI protected final WireFormat wireFormat; protected int connectionTimeout;//连接超时时间 protected int soTimeout; protected int socketBufferSize;//socket的缓存大小 protected int ioBufferSize; protected boolean closeAsync; protected Socket socket; protected DataOutputStream dataOut;//socket的输出流 protected DataInputStream dataIn;//socket的输入流 protected TimeStampStream buffOut; protected int trafficClass; private boolean trafficClassSet; protected boolean diffServChosen; protected boolean typeOfServiceChosen; protected boolean trace; protected String logWriterName; protected boolean dynamicManagement; protected boolean startLogging; protected int jmxPort; protected boolean useLocalHost; protected int minmumWireFormatVersion; protected SocketFactory socketFactory; protected final AtomicReference stoppedLatch; protected volatile int receiveCounter; private Map socketOptions; private int soLinger; private Boolean keepAlive;//是否保活 private Boolean tcpNoDelay;//tcp是否为非延时 private Thread runnerThread; public TcpTransport(WireFormat wireFormat, SocketFactory socketFactory, URI remoteLocation, URI localLocation) throws UnknownHostException, IOException { connectionTimeout = 30000; socketBufferSize = 65536; ioBufferSize = 8192; closeAsync = true; buffOut = null; trafficClass = 0; trafficClassSet = false; diffServChosen = false; typeOfServiceChosen = false; trace = false; logWriterName = TransportLoggerSupport.defaultLogWriterName; dynamicManagement = false; startLogging = true; jmxPort = 1099; useLocalHost = false; stoppedLatch = new AtomicReference(); soLinger = -2147483648; this.wireFormat = wireFormat; this.socketFactory = socketFactory; try { //默认SOCKET工厂创建socket socket = socketFactory.createSocket(); } this.remoteLocation = remoteLocation; this.localLocation = localLocation; setDaemon(false); } }
//DefaultSocketFactory
class DefaultSocketFactory extends SocketFactory { DefaultSocketFactory() { } public Socket createSocket() { return new Socket(); } }
配置transport
rc = configure(transport, wf, options); public Transport configure(Transport transport, WireFormat wf, Map options) throws Exception { //配置写超时时间 transport = compositeConfigure(transport, wf, options); //创建MutexTransport transport = new MutexTransport(transport); //创建ResponseCorrelator transport = new ResponseCorrelator(transport); return transport; } //配置写超时时间 public Transport compositeConfigure(Transport transport, WireFormat format, Map options) { if(options.containsKey("soWriteTimeout")) { transport = new WriteTimeoutFilter(transport); String soWriteTimeout = (String)options.remove("soWriteTimeout"); if(soWriteTimeout != null) ((WriteTimeoutFilter)transport).setWriteTimeout(Long.parseLong(soWriteTimeout)); } IntrospectionSupport.setProperties(transport, options); return transport; }
//MutexTransport,添加锁机制
public class MutexTransport extends TransportFilter { private final ReentrantLock writeLock; private boolean syncOnCommand; public MutexTransport(Transport next) { super(next); writeLock = new ReentrantLock(); syncOnCommand = false; } public void onCommand(Object command) { if(!syncOnCommand) break MISSING_BLOCK_LABEL_47; writeLock.lock(); transportListener.onCommand(command); writeLock.unlock(); break MISSING_BLOCK_LABEL_57; Exception exception; exception; writeLock.unlock(); throw exception; transportListener.onCommand(command); } ... } //ResponseCorrelator,请求协调器 public class ResponseCorrelator extends TransportFilter { private final Map requestMap; private IntSequenceGenerator sequenceGenerator; private final boolean debug; private IOException error; public ResponseCorrelator(Transport next) { this(next, new IntSequenceGenerator()); } public void oneway(Object o) throws IOException { Command command = (Command)o; command.setCommandId(sequenceGenerator.getNextSequenceId()); command.setResponseRequired(false); next.oneway(command); } public FutureResponse asyncRequest(Object o, ResponseCallback responseCallback) throws IOException { ... } public Object request(Object command) throws IOException { ..... } public void onCommand(Object o) { .... } }
小节一下创建transport:
TransportFactory创建Transport,从TransportFactory的ConcurrentHashMap
获取brokerURI协议对应的TransportFactory,没有则根据brokerURI协议从FactoryFinder的获取,没有则加载,相应的实例。
b.创建连接
从上面看到transport为TransportFactory,factoryStats为JMSStatsImpl
先看一下JMSStatsImpl
public class JMSStatsImpl extends StatsImpl { private List connections; public JMSStatsImpl() { //获取线程安全的connections集合 connections = new CopyOnWriteArrayList(); } public JMSConnectionStatsImpl[] getConnections() { Object connectionArray[] = connections.toArray(); int size = connectionArray.length; JMSConnectionStatsImpl answer[] = new JMSConnectionStatsImpl[size]; for(int i = 0; i < size; i++) { ActiveMQConnection connection = (ActiveMQConnection)connectionArray[i]; answer[i] = connection.getConnectionStats(); } return answer; } public void addConnection(ActiveMQConnection connection) { connections.add(connection); } public void removeConnection(ActiveMQConnection connection) { connections.remove(connection); } public void dump(IndentPrinter out) { out.printIndent(); out.println("factory {"); out.incrementIndent(); JMSConnectionStatsImpl array[] = getConnections(); for(int i = 0; i < array.length; i++) { JMSConnectionStatsImpl connectionStat = array[i]; connectionStat.dump(out); } out.decrementIndent(); out.printIndent(); out.println("}"); out.flush(); } public void setEnabled(boolean enabled) { super.setEnabled(enabled); JMSConnectionStatsImpl stats[] = getConnections(); int size = stats.length; for(int i = 0; i < size; i++) stats[i].setEnabled(enabled); } }
从上JMSStatsImpl为管理连接的ActiveMQConnection
回到
connection = createActiveMQConnection(transport, factoryStats);
//ActiveMQConnectionFactory
protected ActiveMQConnection createActiveMQConnection(Transport transport, JMSStatsImpl stats) throws Exception { ActiveMQConnection connection = new ActiveMQConnection(transport, getClientIdGenerator(), getConnectionIdGenerator(), stats); return connection; }
//ActiveMQConnection
public class ActiveMQConnection implements Connection, TopicConnection, QueueConnection, StatsCapable, Closeable, TransportListener, EnhancedConnection { //默认用户密码brokerURL,线程池大小 public static final String DEFAULT_USER; public static final String DEFAULT_PASSWORD; public static final String DEFAULT_BROKER_URL; public static int DEFAULT_THREAD_POOL_SIZE = 1000; private static final Logger LOG = LoggerFactory.getLogger(org/apache/activemq/ActiveMQConnection); //TempDestinations public final ConcurrentMap activeTempDestinations = new ConcurrentHashMap(); protected boolean dispatchAsync;//是否异步分发消息 protected boolean alwaysSessionAsync; private TaskRunnerFactory sessionTaskRunner;//会话任务线程工厂 private final ThreadPoolExecutor executor;//线程执行器 private final ConnectionInfo info;//连接信息 private ExceptionListener exceptionListener; private ClientInternalExceptionListener clientInternalExceptionListener; private boolean clientIDSet; private boolean isConnectionInfoSentToBroker; private boolean userSpecifiedClientID; private ActiveMQPrefetchPolicy prefetchPolicy; private BlobTransferPolicy blobTransferPolicy; private RedeliveryPolicyMap redeliveryPolicyMap; private MessageTransformer transformer; private boolean disableTimeStampsByDefault; private boolean optimizedMessageDispatch; private boolean copyMessageOnSend; private boolean useCompression;//是否压缩 private boolean objectMessageSerializationDefered; private boolean useAsyncSend;//是否异步发送 private boolean optimizeAcknowledge; private long optimizeAcknowledgeTimeOut; private long optimizedAckScheduledAckInterval; private boolean nestedMapAndListEnabled; private boolean useRetroactiveConsumer; private boolean exclusiveConsumer; private boolean alwaysSyncSend; private int closeTimeout;//连接关闭超时时间 private boolean watchTopicAdvisories; private long warnAboutUnstartedConnectionTimeout; private int sendTimeout;//发送超时时间 private boolean sendAcksAsync;//是否异步发送Acks private boolean checkForDuplicates; private boolean queueOnlyConnection;//是否为队列连接 private boolean consumerExpiryCheckEnabled; private final Transport transport;//transport private final IdGenerator clientIdGenerator; private final JMSStatsImpl factoryStats;//连接状态管理器 private final JMSConnectionStatsImpl stats; //启动动关闭状态AtomicBoolean private final AtomicBoolean started = new AtomicBoolean(false); private final AtomicBoolean closing = new AtomicBoolean(false); private final AtomicBoolean closed = new AtomicBoolean(false); private final AtomicBoolean transportFailed = new AtomicBoolean(false); //会话,消费者连接, private final CopyOnWriteArrayList sessions = new CopyOnWriteArrayList(); private final CopyOnWriteArrayList connectionConsumers = new CopyOnWriteArrayList(); private final CopyOnWriteArrayList transportListeners = new CopyOnWriteArrayList(); //dispatchers private final ConcurrentMap dispatchers = new ConcurrentHashMap(); //生产者 private final ConcurrentMap producers = new ConcurrentHashMap(); //会话消费者id private final LongSequenceGenerator sessionIdGenerator = new LongSequenceGenerator(); private final SessionId connectionSessionId; private final LongSequenceGenerator consumerIdGenerator = new LongSequenceGenerator(); private final LongSequenceGenerator tempDestinationIdGenerator = new LongSequenceGenerator(); private final LongSequenceGenerator localTransactionIdGenerator = new LongSequenceGenerator(); private AdvisoryConsumer advisoryConsumer; private final CountDownLatch brokerInfoReceived = new CountDownLatch(1); //broker信息 private BrokerInfo brokerInfo; private IOException firstFailureError; private int producerWindowSize; private final AtomicInteger protocolVersion = new AtomicInteger(11); private final long timeCreated = System.currentTimeMillis(); private final ConnectionAudit connectionAudit = new ConnectionAudit(); private DestinationSource destinationSource; private final Object ensureConnectionInfoSentMutex = new Object(); private boolean useDedicatedTaskRunner; protected AtomicInteger transportInterruptionProcessingComplete; private long consumerFailoverRedeliveryWaitPeriod; //调度器 private Scheduler scheduler; private boolean messagePrioritySupported; private boolean transactedIndividualAck; private boolean nonBlockingRedelivery; private boolean rmIdFromConnectionId; private int maxThreadPoolSize; private RejectedExecutionHandler rejectedTaskHandler; static { DEFAULT_USER = ActiveMQConnectionFactory.DEFAULT_USER; DEFAULT_PASSWORD = ActiveMQConnectionFactory.DEFAULT_PASSWORD; DEFAULT_BROKER_URL = ActiveMQConnectionFactory.DEFAULT_BROKER_URL; } }
再看起构造
protected ActiveMQConnection(final Transport transport, IdGenerator clientIdGenerator, IdGenerator connectionIdGenerator, JMSStatsImpl factoryStats) throws Exception { dispatchAsync = true; alwaysSessionAsync = true; prefetchPolicy = new ActiveMQPrefetchPolicy(); optimizedMessageDispatch = true; copyMessageOnSend = true; optimizeAcknowledgeTimeOut = 0L; optimizedAckScheduledAckInterval = 0L; nestedMapAndListEnabled = true; closeTimeout = 15000; watchTopicAdvisories = true; warnAboutUnstartedConnectionTimeout = 500L; sendTimeout = 0; sendAcksAsync = true; checkForDuplicates = true; queueOnlyConnection = false; consumerExpiryCheckEnabled = true; producerWindowSize = 0; transportInterruptionProcessingComplete = new AtomicInteger(0); messagePrioritySupported = false; transactedIndividualAck = false; nonBlockingRedelivery = false; rmIdFromConnectionId = false; maxThreadPoolSize = DEFAULT_THREAD_POOL_SIZE; rejectedTaskHandler = null; this.transport = transport; this.clientIdGenerator = clientIdGenerator; this.factoryStats = factoryStats; executor = new ThreadPoolExecutor(1, 1, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue(), new ThreadFactory() { public Thread newThread(Runnable r) { Thread thread = new Thread(r, (new StringBuilder()).append("ActiveMQ Connection Executor: ").append(transport).toString()); return thread; } //ThreadPoolExecutor关联一个Transport和ActiveMQConnection final Transport val$transport; final ActiveMQConnection this$0; { this$0 = ActiveMQConnection.this; transport = transport1; super(); } }); //连接信息 String uniqueId = connectionIdGenerator.generateId(); info = new ConnectionInfo(new ConnectionId(uniqueId)); info.setManageable(true); info.setFaultTolerant(transport.isFaultTolerant()); //会话信息 connectionSessionId = new SessionId(info.getConnectionId(), -1L); this.transport.setTransportListener(this); //将连接信息,添加到连接管理器 stats = new JMSConnectionStatsImpl(sessions, this instanceof XAConnection); this.factoryStats.addConnection(this); connectionAudit.setCheckForDuplicates(transport.isFaultTolerant()); }
c.设置连接用户密码
connection.setUserName(userName); connection.setPassword(password);
protected void setUserName(String userName) { info.setUserName(userName); }
public class ConnectionInfo extends BaseCommand { public static final byte DATA_STRUCTURE_TYPE = 3; protected ConnectionId connectionId; protected String clientId; protected String clientIp; protected String userName; protected String password; protected BrokerId brokerPath[]; protected boolean brokerMasterConnector;//是否为集群 protected boolean manageable; protected boolean clientMaster; protected boolean faultTolerant; protected boolean failoverReconnect; protected transient Object transportContext; }
d.配置连接
configureConnection(connection);
protected void configureConnection(ActiveMQConnection connection) throws JMSException { //配置连接会话连接属性 connection.setPrefetchPolicy(getPrefetchPolicy()); connection.setDisableTimeStampsByDefault(isDisableTimeStampsByDefault()); connection.setOptimizedMessageDispatch(isOptimizedMessageDispatch()); connection.setCopyMessageOnSend(isCopyMessageOnSend()); connection.setUseCompression(isUseCompression()); connection.setObjectMessageSerializationDefered(isObjectMessageSerializationDefered()); connection.setDispatchAsync(isDispatchAsync()); connection.setUseAsyncSend(isUseAsyncSend()); connection.setAlwaysSyncSend(isAlwaysSyncSend()); connection.setAlwaysSessionAsync(isAlwaysSessionAsync()); connection.setOptimizeAcknowledge(isOptimizeAcknowledge()); connection.setOptimizeAcknowledgeTimeOut(getOptimizeAcknowledgeTimeOut()); connection.setOptimizedAckScheduledAckInterval(getOptimizedAckScheduledAckInterval()); connection.setUseRetroactiveConsumer(isUseRetroactiveConsumer()); connection.setExclusiveConsumer(isExclusiveConsumer()); connection.setRedeliveryPolicyMap(getRedeliveryPolicyMap()); connection.setTransformer(getTransformer()); connection.setBlobTransferPolicy(getBlobTransferPolicy().copy()); connection.setWatchTopicAdvisories(isWatchTopicAdvisories()); connection.setProducerWindowSize(getProducerWindowSize()); connection.setWarnAboutUnstartedConnectionTimeout(getWarnAboutUnstartedConnectionTimeout()); connection.setSendTimeout(getSendTimeout()); connection.setCloseTimeout(getCloseTimeout()); connection.setSendAcksAsync(isSendAcksAsync()); connection.setAuditDepth(getAuditDepth()); connection.setAuditMaximumProducerNumber(getAuditMaximumProducerNumber()); connection.setUseDedicatedTaskRunner(isUseDedicatedTaskRunner()); connection.setConsumerFailoverRedeliveryWaitPeriod(getConsumerFailoverRedeliveryWaitPeriod()); connection.setCheckForDuplicates(isCheckForDuplicates()); connection.setMessagePrioritySupported(isMessagePrioritySupported()); connection.setTransactedIndividualAck(isTransactedIndividualAck()); connection.setNonBlockingRedelivery(isNonBlockingRedelivery()); connection.setMaxThreadPoolSize(getMaxThreadPoolSize()); connection.setSessionTaskRunner(getSessionTaskRunner()); connection.setRejectedTaskHandler(getRejectedTaskHandler()); connection.setNestedMapAndListEnabled(isNestedMapAndListEnabled()); connection.setRmIdFromConnectionId(isRmIdFromConnectionId()); connection.setConsumerExpiryCheckEnabled(isConsumerExpiryCheckEnabled()); if(transportListener != null) connection.addTransportListener(transportListener); if(exceptionListener != null) connection.setExceptionListener(exceptionListener); if(clientInternalExceptionListener != null) connection.setClientInternalExceptionListener(clientInternalExceptionListener); }
e.启动transport
transport.start();
//启动TcpTransport线程
public class TcpTransport extends TransportThreadSupport implements Transport, Service, Runnable{ public void run() { LOG.trace((new StringBuilder()).append("TCP consumer thread for ").append(this).append(" starting").toString()); runnerThread = Thread.currentThread(); for(; !isStopped(); doRun()); } protected void doRun() throws IOException { try { //消费命令 Object command = readCommand(); //开始消费 doConsume(command); } }
而doConsume在TcpTransport中没有,TransportThreadSupport也没有,看TransportSupport
public abstract class TransportThreadSupport extends TransportSupport implements Runnable //TransportSupport public abstract class TransportSupport extends ServiceSupport implements Transport { TransportListener transportListener;//消息监听器 public void doConsume(Object command) { if(command != null) if(transportListener != null) //启动监听器,监听消息,如果消息监听器不为空, transportListener.onCommand(command); else LOG.error((new StringBuilder()).append("No transportListener available to process inbound command: ").append(command).toString()); } }
//service辅助类
public abstract class ServiceSupport implements Service { private AtomicBoolean started; private AtomicBoolean stopping; private AtomicBoolean stopped; private List serviceListeners; public ServiceSupport() { started = new AtomicBoolean(false); stopping = new AtomicBoolean(false); stopped = new AtomicBoolean(false); //新建线程安全的服务监听器 serviceListeners = new CopyOnWriteArrayList(); } //终于找这个了,因为在TcpTransPort中看到dostart(),就不知道怎么调的, //ActiveMQ的Service和Tomcat的lifecyle是一回事,管理组件生命周期 public void start() throws Exception { boolean success; if(!started.compareAndSet(false, true)) break MISSING_BLOCK_LABEL_93; success = false; stopped.set(false); preStart(); //调用dostart而,doStart为抽象函数待父类扩展 doStart(); success = true; started.set(success); //启动service监听器 for(Iterator i$ = serviceListeners.iterator(); i$.hasNext(); l.started(this)) l = (ServiceListener)i$.next(); } } //待父类扩展 protected abstract void doStart() throws Exception; }
看TcpTransport
public class TcpTransport extends TransportThreadSupport implements Transport, Service, Runnable { protected void doStart() throws Exception { //连接 connect(); stoppedLatch.set(new CountDownLatch(1)); //启动TransportThreadSupport线程 super.doStart(); } }
来看
//连接
connect();
protected void connect() throws Exception { if(socket == null && socketFactory == null) throw new IllegalStateException("Cannot connect if the socket or socketFactory have not been set"); InetSocketAddress localAddress = null; InetSocketAddress remoteAddress = null; if(localLocation != null) //如果是localhost地址,则创建InetSocketAddress localAddress = new InetSocketAddress(InetAddress.getByName(localLocation.getHost()), localLocation.getPort()); if(remoteLocation != null) { //如果是ip地址,则根据ip创建InetSocketAddress String host = resolveHostName(remoteLocation.getHost()); remoteAddress = new InetSocketAddress(host, remoteLocation.getPort()); } trafficClassSet = setTrafficClass(socket); if(socket != null) { if(localAddress != null) socket.bind(localAddress); if(remoteAddress != null) if(connectionTimeout >= 0) //socket连接broker socket.connect(remoteAddress, connectionTimeout); else socket.connect(remoteAddress); } else if(localAddress != null) socket = socketFactory.createSocket(remoteAddress.getAddress(), remoteAddress.getPort(), localAddress.getAddress(), localAddress.getPort()); else socket = socketFactory.createSocket(remoteAddress.getAddress(), remoteAddress.getPort()); //初始化socket initialiseSocket(socket); //初始化输入输出流 initializeStreams(); }
初始化socket
initialiseSocket(socket);
protected void initialiseSocket(Socket sock) throws SocketException, IllegalArgumentException { if(socketOptions != null) { Map copy = new HashMap(socketOptions); IntrospectionSupport.setProperties(socket, copy); if(!copy.isEmpty()) throw new IllegalArgumentException((new StringBuilder()).append("Invalid socket parameters: ").append(copy).toString()); } try { //设置socket接收与发送缓存区大小 sock.setReceiveBufferSize(socketBufferSize); sock.setSendBufferSize(socketBufferSize); } catch(SocketException se) { LOG.warn((new StringBuilder()).append("Cannot set socket buffer size = ").append(socketBufferSize).toString()); LOG.debug((new StringBuilder()).append("Cannot set socket buffer size. Reason: ").append(se.getMessage()).append(". This exception is ignored.").toString(), se); } //设置socket写超时时间 sock.setSoTimeout(soTimeout); if(keepAlive != null) //设置socket保活 sock.setKeepAlive(keepAlive.booleanValue()); if(soLinger > -1) sock.setSoLinger(true, soLinger); else if(soLinger == -1) sock.setSoLinger(false, 0); if(tcpNoDelay != null) //设置socket是否有延时 sock.setTcpNoDelay(tcpNoDelay.booleanValue()); if(!trafficClassSet) trafficClassSet = setTrafficClass(sock); }
初始化输入输出流
initializeStreams();
protected void initializeStreams() throws Exception { //创建Tcp缓存区输入流 TcpBufferedInputStream buffIn = new TcpBufferedInputStream(socket.getInputStream(), ioBufferSize) { public int read() throws IOException { receiveCounter++; return super.read(); } public int read(byte b[], int off, int len) throws IOException { receiveCounter++; return super.read(b, off, len); } public long skip(long n) throws IOException { receiveCounter++; return super.skip(n); } protected void fill() throws IOException { receiveCounter++; super.fill(); } final TcpTransport this$0; { this$0 = TcpTransport.this; super(x0, x1); } }; //创建数据输入流 dataIn = new DataInputStream(buffIn); //创建tcp输出流 TcpBufferedOutputStream outputStream = new TcpBufferedOutputStream(socket.getOutputStream(), ioBufferSize); //创建数据输出流 dataOut = new DataOutputStream(outputStream); buffOut = outputStream; }
再看TransportThreadSupport
//TransportThreadSupport
public abstract class TransportThreadSupport extends TransportSupport implements Runnable { private boolean daemon; private Thread runner; private long stackSize; //启动TransportThread线程 protected void doStart() throws Exception { runner = new Thread(null, this, (new StringBuilder()).append("ActiveMQ Transport: ").append(toString()).toString(), stackSize); runner.setDaemon(daemon); runner.start(); } }
从上可以看出启动transport,就是启动transport监听器和Service监听器,同时初始化Socket及
transport的数据输入DataInputStream,输出流DataOutputStream
再来看
启动连接
connection.start(); public void start() throws JMSException { checkClosedOrFailed(); ensureConnectionInfoSent(); if(started.compareAndSet(false, true)) { ActiveMQSession session; //启动会话 for(Iterator i = sessions.iterator(); i.hasNext(); session.start()) session = (ActiveMQSession)i.next(); } }
今天现将这么多剩下的下一篇来讲,总结一下:
ActiveMQConnectionFactory的创建过程,主要为初始化为broker url,用户密码,是否压缩、异步发送消息、支持消息优先级、非阻塞传输,最大线程数,生产窗口大小等属性;从ActiveMQConnectionFactory创建连接,首先通过TcpTransportFacotory创建TcpTransport,然后保证成待锁机制的MutexTransport,最后包装成
ResponseCorrelator;根据TcpTransport和ActiveMQConnection状态管理器JMSStatsImpl创建ActiveMQConnection,创建ActiveMQConnection过程中,主要是是否异步分发消息,线程执行器,连接状态管理器,调度器等;然后设置连接用户密码通过ConnectionInfo,配置是否支持消息优先级、非阻塞传输,最大线程数,生产窗口大小,Transport监听器transportListener;
最后启动TcpTransport和Connection,启动TcpTransport主要是初始化socket,
ip,端口,输入输出缓存区,输入输出流DataI/OnputStream,启动连接主要启动会话ActiveMQSession,这个我们在后面再看,以及3,4,5,6。
3.会话
Session session = connection.createSession(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);
4.消息队列和订阅主题
Queue destination = session.createQueue(qname); Topic destination = session.createTopic(tname);
5.创建生产者
MessageProducer producer = session.createProducer(destination); producer.setDeliveryMode(DeliveryMode.PERSISTENT);
6.发送消息
sendMessage(session, producer);
Queue public static void sendMessage(Session session, MessageProducer producer) throws Exception { for (int i = 1; i <= 5; i++) {//有限制,达到1000就不行 TextMessage message = session.createTextMessage("向ActiveMq发送的Queue消息" + i); // 发送消息到目的地方 System.out.println("发送消息:" + "ActiveMq 发送的Queue消息" + i); producer.send(message); } } Topic /** * * @param session * @param producer * @throws Exception */ public static void sendMessage(Session session, MessageProducer producer) throws Exception { Order order = new Order(); order.setId(1); order.setAmount(150.62); order.setGoodsId(15); order.setGoodsAmount(2); order.setShopId(5656); //我们也可以将Object转换为Json String,作为TextMessage来传送,在消费再反Json String 为Obejct ObjectMessage orderMess = session.createObjectMessage(order); System.out.println("向ActiveMq:"+tname+"发送订单信息:" + "ActiveMq 发送的Topic消息"); producer.send(orderMess); }
//ConnectionFactory
package javax.jms; public interface ConnectionFactory { public abstract Connection createConnection() throws JMSException; public abstract Connection createConnection(String s, String s1) throws JMSException; }
//QueueConnectionFactory
package javax.jms; public interface QueueConnectionFactory extends ConnectionFactory { public abstract QueueConnection createQueueConnection() throws JMSException; public abstract QueueConnection createQueueConnection(String s, String s1) throws JMSException; }
//TopicConnectionFactory
package javax.jms; public interface TopicConnectionFactory extends ConnectionFactory { public abstract TopicConnection createTopicConnection() throws JMSException; public abstract TopicConnection createTopicConnection(String s, String s1) throws JMSException; }
//IdGenerator 客户端,连接ID产生器
public class IdGenerator { private static final String UNIQUE_STUB; private static int instanceCount; private static String hostName; private String seed; private final AtomicLong sequence; private int length; public static final String PROPERTY_IDGENERATOR_HOSTNAME = "activemq.idgenerator.hostname"; public static final String PROPERTY_IDGENERATOR_LOCALPORT = "activemq.idgenerator.localport"; public static final String PROPERTY_IDGENERATOR_PORT = "activemq.idgenerator.port"; public IdGenerator(String prefix) { sequence = new AtomicLong(1L); synchronized(UNIQUE_STUB) { seed = (new StringBuilder()).append(prefix).append(UNIQUE_STUB).append(instanceCount++).append(":").toString(); length = seed.length() + "9223372036854775807".length(); } } public synchronized String generateId() { StringBuilder sb = new StringBuilder(length); sb.append(seed); sb.append(sequence.getAndIncrement()); return sb.toString(); } }
//QueueConnection
public interface QueueConnection extends Connection { public abstract QueueSession createQueueSession(boolean flag, int i) throws JMSException; public abstract ConnectionConsumer createConnectionConsumer(Queue queue, String s, ServerSessionPool serversessionpool, int i) throws JMSException; }
//TopicConnection
public interface TopicConnection extends Connection { public abstract TopicSession createTopicSession(boolean flag, int i) throws JMSException; public abstract ConnectionConsumer createConnectionConsumer(Topic topic, String s, ServerSessionPool serversessionpool, int i) throws JMSException; public abstract ConnectionConsumer createDurableConnectionConsumer(Topic topic, String s, String s1, ServerSessionPool serversessionpool, int i) throws JMSException; }
//Cloneable
package java.lang; /** * A class implements theCloneable
interface to * indicate to the {@link java.lang.Object#clone()} method that it * is legal for that method to make a * field-for-field copy of instances of that class. ** Invoking Object's clone method on an instance that does not implement the *
Cloneable
interface results in the exception *CloneNotSupportedException
being thrown. ** By convention, classes that implement this interface should override * Object.clone (which is protected) with a public method. * See {@link java.lang.Object#clone()} for details on overriding this * method. *
* Note that this interface does not contain the clone method. * Therefore, it is not possible to clone an object merely by virtue of the * fact that it implements this interface. Even if the clone method is invoked * reflectively, there is no guarantee that it will succeed. * * @author unascribed * @see java.lang.CloneNotSupportedException * @see java.lang.Object#clone() * @since JDK1.0 */ public interface Cloneable { }