1,发送消息入口

  Message message = messageBean.getMessageCreator().createMessage(session);
producer.send(message);

2,调用ActiveMQMessageProducerSupport的send方法。

该类实现了MessageProducer接口

 public void send(Message message) throws JMSException {
this.send(this.getDestination(),
message,
this.defaultDeliveryMode,
this.defaultPriority,
this.defaultTimeToLive);
} public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive, AsyncCallback onComplete) throws JMSException {
checkClosed();
if (destination == null) {
if (info.getDestination() == null) {
throw new UnsupportedOperationException("A destination must be specified.");
}
throw new InvalidDestinationException("Don't understand null destinations");
} ActiveMQDestination dest;
if (destination.equals(info.getDestination())) {
dest = (ActiveMQDestination)destination;
} else if (info.getDestination() == null) {
dest = ActiveMQDestination.transform(destination);
} else {
throw new UnsupportedOperationException("This producer can only send messages to: " + this.info.getDestination().getPhysicalName());
}
if (dest == null) {
throw new JMSException("No destination specified");
} if (transformer != null) {
Message transformedMessage = transformer.producerTransform(session, this, message);
if (transformedMessage != null) {
message = transformedMessage;
}
} if (producerWindow != null) {
try {
producerWindow.waitForSpace();
} catch (InterruptedException e) {
throw new JMSException("Send aborted due to thread interrupt.");
}
} this.session.send(this, dest, message, deliveryMode, priority, timeToLive, producerWindow, sendTimeout, onComplete); stats.onMessage();
}

3调用ActiveMQSession的send接口进行消息发送

protected void send(ActiveMQMessageProducer producer, ActiveMQDestination destination, Message message, int deliveryMode, int priority, long timeToLive,
MemoryUsage producerWindow, int sendTimeout, AsyncCallback onComplete) throws JMSException { checkClosed();
if (destination.isTemporary() && connection.isDeleted(destination)) {
throw new InvalidDestinationException("Cannot publish to a deleted Destination: " + destination);
}
synchronized (sendMutex) {
// tell the Broker we are about to start a new transaction
doStartTransaction();
TransactionId txid = transactionContext.getTransactionId();
long sequenceNumber = producer.getMessageSequence(); //Set the "JMS" header fields on the original message, see 1.1 spec section 3.4.11
message.setJMSDeliveryMode(deliveryMode);
long expiration = 0L;
if (!producer.getDisableMessageTimestamp()) {
long timeStamp = System.currentTimeMillis();
message.setJMSTimestamp(timeStamp);
if (timeToLive > 0) {
expiration = timeToLive + timeStamp;
}
}
message.setJMSExpiration(expiration);
message.setJMSPriority(priority);
message.setJMSRedelivered(false); // transform to our own message format here
ActiveMQMessage msg = ActiveMQMessageTransformation.transformMessage(message, connection); // Set the message id.
if (msg == message) {
msg.setMessageId(new MessageId(producer.getProducerInfo().getProducerId(), sequenceNumber));
} else {
msg.setMessageId(new MessageId(producer.getProducerInfo().getProducerId(), sequenceNumber));
message.setJMSMessageID(msg.getMessageId().toString());
}
//clear the brokerPath in case we are re-sending this message
msg.setBrokerPath(null);
// destination format is provider specific so only set on transformed message
msg.setJMSDestination(destination); msg.setTransactionId(txid);
if (connection.isCopyMessageOnSend()) {
msg = (ActiveMQMessage)msg.copy();
}
msg.setConnection(connection);
msg.onSend();
msg.setProducerId(msg.getMessageId().getProducerId());
if (LOG.isTraceEnabled()) {
LOG.trace(getSessionId() + " sending message: " + msg);
}
if (onComplete==null && sendTimeout <= 0 && !msg.isResponseRequired() && !connection.isAlwaysSyncSend() && (!msg.isPersistent() || connection.isUseAsyncSend() || txid != null)) {
this.connection.asyncSendPacket(msg);
if (producerWindow != null) {
// Since we defer lots of the marshaling till we hit the
// wire, this might not
// provide and accurate size. We may change over to doing
// more aggressive marshaling,
// to get more accurate sizes.. this is more important once
// users start using producer window
// flow control.
int size = msg.getSize();
producerWindow.increaseUsage(size);
}
} else {
if (sendTimeout > 0 && onComplete==null) {
this.connection.syncSendPacket(msg,sendTimeout);
}else {
this.connection.syncSendPacket(msg, onComplete);
}
} }
}

4,ActiveMQConnection发送消息

    public Response syncSendPacket(Command command) throws JMSException {
if (isClosed()) {
throw new ConnectionClosedException();
} else { try {
Response response = (Response)this.transport.request(command);
if (response.isException()) {
ExceptionResponse er = (ExceptionResponse)response;
if (er.getException() instanceof JMSException) {
throw (JMSException)er.getException();
} else {
if (isClosed()||closing.get()) {
LOG.debug("Received an exception but connection is closing");
}
JMSException jmsEx = null;
try {
jmsEx = JMSExceptionSupport.create(er.getException());
} catch(Throwable e) {
LOG.error("Caught an exception trying to create a JMSException for " +er.getException(),e);
}
//dispose of transport for security exceptions
if (er.getException() instanceof SecurityException && command instanceof ConnectionInfo){
Transport t = this.transport;
if (null != t){
ServiceSupport.dispose(t);
}
}
if (jmsEx !=null) {
throw jmsEx;
}
}
}
return response;
} catch (IOException e) {
throw JMSExceptionSupport.create(e);
}
}
} public Response syncSendPacket(Command command) throws JMSException {
if (isClosed()) {
throw new ConnectionClosedException();
} else { try {
Response response = (Response)this.transport.request(command);
if (response.isException()) {
ExceptionResponse er = (ExceptionResponse)response;
if (er.getException() instanceof JMSException) {
throw (JMSException)er.getException();
} else {
if (isClosed()||closing.get()) {
LOG.debug("Received an exception but connection is closing");
}
JMSException jmsEx = null;
try {
jmsEx = JMSExceptionSupport.create(er.getException());
} catch(Throwable e) {
LOG.error("Caught an exception trying to create a JMSException for " +er.getException(),e);
}
//dispose of transport for security exceptions
if (er.getException() instanceof SecurityException && command instanceof ConnectionInfo){
Transport t = this.transport;
if (null != t){
ServiceSupport.dispose(t);
}
}
if (jmsEx !=null) {
throw jmsEx;
}
}
}
return response;
} catch (IOException e) {
throw JMSExceptionSupport.create(e);
}
}
}

5,ResponseCorrelator发送request

    public Object request(Object command) throws IOException {
FutureResponse response = asyncRequest(command, null);
return response.getResult();
}
public FutureResponse asyncRequest(Object o, ResponseCallback responseCallback) throws IOException {
Command command = (Command) o;
command.setCommandId(sequenceGenerator.getNextSequenceId());
command.setResponseRequired(true);
FutureResponse future = new FutureResponse(responseCallback);
IOException priorError = null;
synchronized (requestMap) {
priorError = this.error;
if (priorError == null) {
requestMap.put(new Integer(command.getCommandId()), future);
}
} if (priorError != null) {
future.set(new ExceptionResponse(priorError));
throw priorError;
} next.oneway(command);
return future;
}

6,调用MutexTransport来发送消息

    @Override
public void oneway(Object command) throws IOException {
writeLock.lock();
try {
next.oneway(command);
} finally {
writeLock.unlock();
}
}

7,调用AbstractInactivityMonitor完毕消息发送准备

    public void oneway(Object o) throws IOException {
// To prevent the inactivity monitor from sending a message while we
// are performing a send we take a read lock. The inactivity monitor
// sends its Heart-beat commands under a write lock. This means that
// the MutexTransport is still responsible for synchronizing sends
this.sendLock.readLock().lock();
inSend.set(true);
try {
doOnewaySend(o);
} finally {
commandSent.set(true);
inSend.set(false);
this.sendLock.readLock().unlock();
}
} private void doOnewaySend(Object command) throws IOException {
if( failed.get() ) {
throw new InactivityIOException("Cannot send, channel has already failed: "+next.getRemoteAddress());
}
if (command.getClass() == WireFormatInfo.class) {
synchronized (this) {
processOutboundWireFormatInfo((WireFormatInfo) command);
}
}
next.oneway(command);
}

8。调用TcpTransport。OpenWireFormat,DataOutputStream终于完毕通过tcp发送消息

   public void oneway(Object command) throws IOException {
checkStarted();
wireFormat.marshal(command, dataOut);
dataOut.flush();
}
public synchronized void marshal(Object o, DataOutput dataOut) throws IOException { if (cacheEnabled) {
runMarshallCacheEvictionSweep();
} int size = 1;
if (o != null) { DataStructure c = (DataStructure)o;
byte type = c.getDataStructureType();
DataStreamMarshaller dsm = (DataStreamMarshaller)dataMarshallers[type & 0xFF];
if (dsm == null) {
throw new IOException("Unknown data type: " + type);
}
if (tightEncodingEnabled) {
BooleanStream bs = new BooleanStream();
size += dsm.tightMarshal1(this, c, bs);
size += bs.marshalledSize(); if (!sizePrefixDisabled) {
dataOut.writeInt(size);
} dataOut.writeByte(type);
bs.marshal(dataOut);
dsm.tightMarshal2(this, c, dataOut, bs); } else {
DataOutput looseOut = dataOut; if (!sizePrefixDisabled) {
bytesOut.restart();
looseOut = bytesOut;
} looseOut.writeByte(type);
dsm.looseMarshal(this, c, looseOut); if (!sizePrefixDisabled) {
ByteSequence sequence = bytesOut.toByteSequence();
dataOut.writeInt(sequence.getLength());
dataOut.write(sequence.getData(), sequence.getOffset(), sequence.getLength());
} } } else {
if (!sizePrefixDisabled) {
dataOut.writeInt(size);
}
dataOut.writeByte(NULL_TYPE);
}
}
public final void writeInt(int v) throws IOException {
out.write((v >>> 24) & 0xFF);
out.write((v >>> 16) & 0xFF);
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(4);
}

附图

备注:MessageId是通过ProducerId+sequenceNumber来生成的,sequenceNumber通过原子变量的加1完毕

activeMq发送消息流程的更多相关文章

  1. 【Java Web开发学习】Spring消息-ActiveMQ发送消息

    ActiveMQ发送消息 转载:http://www.cnblogs.com/yangchongxing/p/9042401.html Java消息服务(Java Message Service, J ...

  2. KafkaProducer 发送消息流程

    Kafka 的 Producer 发送消息采用的是异步发送的方式.在消息发送的过程中,涉及到了 两个线程--main 线程和 Sender 线程,以及一个线程共享变量--RecordAccumulat ...

  3. jmeter向ActiveMQ发送消息_广播/订阅(Topics 队列)

    问题描述:测试中需要模拟大量设备的消息上报到平台,但是实际测试中没有那么多设备,所以采取用jmeter直接往ActiveMQ模拟发送设备消息 解决思路:获取平台采取的是Queues还是Topics : ...

  4. 新浪微博发送消息和授权机制原理(WeiboSDK)

    1.首先是在微博发送消息,对于刚開始做weibo发送消息的刚開始学习的人会有一个误区,那就是会觉得须要授权后才干够发送消息.事实上发送消息仅仅须要几行代码就能够实现了,很easy,不须要先授权再发送消 ...

  5. ActiveMQ producer不断发送消息,会导致broker内存耗尽吗?

    http://activemq.apache.org/my-producer-blocks.html 回答了这个问题: ActiveMQ 5.x 支持Message Cursors,它默认把消息从内存 ...

  6. ActiveMQ producer同步/异步发送消息

    http://activemq.apache.org/async-sends.html producer发送消息有同步和异步两种模式,可以通过代码配置: ((ActiveMQConnection)co ...

  7. ACtiveMQ中间件-消息的接收和发送

    一.发送消息基本步骤 (1)启动ActiveMQ的的activemq.bat批处理文件或BrokerService节点 (2)创建连接使用的工厂类ActiveMQConnectionFactory通过 ...

  8. php 事务处理,ActiveMQ的发送消息,与处理消息

    可以通过链式发送->处理->发送...的方式处理类似事务型业务逻辑 比如 发送一个注册消息,消息队列处理完注册以后,紧接着发送一个新手优惠券赠送,赠送完再发一个其它后续逻辑处理的消息等待后 ...

  9. ActiveMQ实现消息的发送与接受

    activemq是apache的一个JMS接口的实现产品,java中定义了JMS规范,虽然RocketMQ,kafka现在比较火,但是还是建议先学一下activeMQ再学其他两个就容易很多 首先可以下 ...

随机推荐

  1. UTF-8 与 BIG-5 转码

    BIG-5 轉 UTF-8 若要將一個文字檔從 BIG-5 編碼轉換為 UTF-8 編碼,可以執行: iconv -f BIG-5 -t UTF-8 big5.txt > utf8.txt 其中 ...

  2. 全网第二好懂的FFT(快速傅里叶变换)

    声明:本FFT是针对OI的.专业人员请出门左拐. Ⅰ前言 很久以前,我打算学习FFT. 然而,算法导论讲的很详细,却看不懂.网上博客更别说了,什么频率之类的都来了.我暗自下了决心:写一篇人看得懂的FF ...

  3. hdu 1384 Intervals (差分约束)

    Intervals Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  4. 【树形dp】Find Metal Mineral

    [HDU4003]Find Metal Mineral Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (J ...

  5. 【后缀自动机】hdu6194 string string string

    题意:给你一个字符串和一个正整数K,让你输出恰好出现K次的子串的数量. 对后缀链接树进行dp预处理后,SAM每个点的endpos大小就是该点结尾的子串出现的次数,maxlen-minlen+1就是子串 ...

  6. Eclipse、svn插件、subclipse的安装

    1.下载subclipse的安装包       URL:http://subclipse.tigris.org/servlets/ProjectDocumentList?folderID=2240   ...

  7. HDU 2859 Phalanx (DP)

    Phalanx Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  8. DockManager

    Devexpress----DockManager类似VS左右上下浮动栏停靠DockManager->Customize->DockPanel->NEW->Text='详细': ...

  9. easyui-textbox input输入框的一种取值方式

    1.html文件 <td> <input id="clientPhone" type="text" name="clientPhon ...

  10. hue启用ldap

    [desktop] [[auth]] …… …… backend=desktop.auth.backend.LdapBackend .….. http://gethue.com/ldap-or-pam ...