activeMq发送消息流程
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发送消息流程的更多相关文章
- 【Java Web开发学习】Spring消息-ActiveMQ发送消息
ActiveMQ发送消息 转载:http://www.cnblogs.com/yangchongxing/p/9042401.html Java消息服务(Java Message Service, J ...
- KafkaProducer 发送消息流程
Kafka 的 Producer 发送消息采用的是异步发送的方式.在消息发送的过程中,涉及到了 两个线程--main 线程和 Sender 线程,以及一个线程共享变量--RecordAccumulat ...
- jmeter向ActiveMQ发送消息_广播/订阅(Topics 队列)
问题描述:测试中需要模拟大量设备的消息上报到平台,但是实际测试中没有那么多设备,所以采取用jmeter直接往ActiveMQ模拟发送设备消息 解决思路:获取平台采取的是Queues还是Topics : ...
- 新浪微博发送消息和授权机制原理(WeiboSDK)
1.首先是在微博发送消息,对于刚開始做weibo发送消息的刚開始学习的人会有一个误区,那就是会觉得须要授权后才干够发送消息.事实上发送消息仅仅须要几行代码就能够实现了,很easy,不须要先授权再发送消 ...
- ActiveMQ producer不断发送消息,会导致broker内存耗尽吗?
http://activemq.apache.org/my-producer-blocks.html 回答了这个问题: ActiveMQ 5.x 支持Message Cursors,它默认把消息从内存 ...
- ActiveMQ producer同步/异步发送消息
http://activemq.apache.org/async-sends.html producer发送消息有同步和异步两种模式,可以通过代码配置: ((ActiveMQConnection)co ...
- ACtiveMQ中间件-消息的接收和发送
一.发送消息基本步骤 (1)启动ActiveMQ的的activemq.bat批处理文件或BrokerService节点 (2)创建连接使用的工厂类ActiveMQConnectionFactory通过 ...
- php 事务处理,ActiveMQ的发送消息,与处理消息
可以通过链式发送->处理->发送...的方式处理类似事务型业务逻辑 比如 发送一个注册消息,消息队列处理完注册以后,紧接着发送一个新手优惠券赠送,赠送完再发一个其它后续逻辑处理的消息等待后 ...
- ActiveMQ实现消息的发送与接受
activemq是apache的一个JMS接口的实现产品,java中定义了JMS规范,虽然RocketMQ,kafka现在比较火,但是还是建议先学一下activeMQ再学其他两个就容易很多 首先可以下 ...
随机推荐
- CentOS7系统防火墙开关、状态与自启
首先需要说明的是CentOS7使用的是firewalld.service,而不是iptables.service [xf@xuexi ~]$ systemctl status firewalld.se ...
- 单能X射线产生方法
主要是荧光 利用布拉格准则, 关键词如下.. 国内有些专利 monochromating crystal spectrometer 物理实验设备名称翻译 ... 单色光检糖计 monochromati ...
- centos7 crontab管理
crontab -l 当前用户的任务 crontab -e 编辑任务列表 crontab -r 删除当前用户的任务
- python队列、线程、进程、协程(转)
原文地址: http://www.cnblogs.com/wangqiaomei/p/5682669.html 一.queue 二.线程 #基本使用 #线程锁 #自定义线程池 #生产者消费者模型(队列 ...
- hdu 1011(Starship Troopers,树形dp)
Starship Troopers Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- 【BZOJ 2802】 2802: [Poi2012]Warehouse Store (贪心)
2802: [Poi2012]Warehouse Store Description 有一家专卖一种商品的店,考虑连续的n天.第i天上午会进货Ai件商品,中午的时候会有顾客需要购买Bi件商品,可以选择 ...
- 【Kruskal】Slim Span
[Uva1395]Slim Span 题目略…… 试题分析:codevs1001舒适的路线上加一个判一下连通性就好,顺便把除改成减 代码: #include<iostream> #incl ...
- vue-cli创建vue项目
原文出处:https://segmentfault.com/a/1190000008922234 第一步 node环境安装 1.1 如果本机没有安装node运行环境,请下载node 安装包进行安装1. ...
- Jedis笔记
Sting: Jedis jedis=RedisClient.getResource(); jedis.set("hello", "world"); Syste ...
- Educational Codeforces Round 8 B. New Skateboard 暴力
B. New Skateboard 题目连接: http://www.codeforces.com/contest/628/problem/A Description Max wants to buy ...