apollo 消息分发源代码分析
1。MessageDispatch消息分发信息
public static final byte DATA_STRUCTURE_TYPE = CommandTypes.MESSAGE_DISPATCH;
protected ConsumerId consumerId;
protected ActiveMQDestination destination;
protected Message message;
protected int redeliveryCounter;
protected transient long deliverySequenceId;
protected transient Object consumer;
protected transient Runnable transmitCallback;
protected transient Throwable rollbackCause;
2,自己主动确认。是再接受到消息,反馈给上层应用之前就给确认
在afterMessageIsConsumed方法中
先deliveredMessages.clear();接着 session.sendAck(ack);
3,在从tcp取到消息后放到unconsumedMessages等待消费
4,在从unconsumedMessages取出消息预处理后。在beforeMessageIsConsumed方法加消息加到deliveredMessages 里面。
unconsumedMessages; 消费者从mq接受到消息存储的位置,还没有消费
5,receive内部消费之前
private void beforeMessageIsConsumed(MessageDispatch md) throws JMSException {
md.setDeliverySequenceId(session.getNextDeliveryId());
lastDeliveredSequenceId = md.getMessage().getMessageId().getBrokerSequenceId();
if (!isAutoAcknowledgeBatch()) {
synchronized(deliveredMessages) {
deliveredMessages.addFirst(md);
}
if (session.getTransacted()) {
if (transactedIndividualAck) {
immediateIndividualTransactedAck(md);
} else {
ackLater(md, MessageAck.DELIVERED_ACK_TYPE);
}
}
}
}
6,receive内部消费之后
private void afterMessageIsConsumed(MessageDispatch md, boolean messageExpired) throws JMSException {
if (unconsumedMessages.isClosed()) {
return;
}
if (messageExpired) {
acknowledge(md, MessageAck.DELIVERED_ACK_TYPE);
stats.getExpiredMessageCount().increment();
} else {
stats.onMessage();
if (session.getTransacted()) {
// Do nothing.
} else if (isAutoAcknowledgeEach()) {
if (deliveryingAcknowledgements.compareAndSet(false, true)) {
synchronized (deliveredMessages) {
if (!deliveredMessages.isEmpty()) {
if (optimizeAcknowledge) {
ackCounter++;
// AMQ-3956 evaluate both expired and normal msgs as
// otherwise consumer may get stalled
if (ackCounter + deliveredCounter >= (info.getPrefetchSize() * .65) || (optimizeAcknowledgeTimeOut > 0 && System.currentTimeMillis() >= (optimizeAckTimestamp + optimizeAcknowledgeTimeOut))) {
MessageAck ack = makeAckForAllDeliveredMessages(MessageAck.STANDARD_ACK_TYPE);
if (ack != null) {
deliveredMessages.clear();
ackCounter = 0;
session.sendAck(ack);
optimizeAckTimestamp = System.currentTimeMillis();
}
// AMQ-3956 - as further optimization send
// ack for expired msgs when there are any.
// This resets the deliveredCounter to 0 so that
// we won't sent standard acks with every msg just
// because the deliveredCounter just below
// 0.5 * prefetch as used in ackLater()
if (pendingAck != null && deliveredCounter > 0) {
session.sendAck(pendingAck);
pendingAck = null;
deliveredCounter = 0;
}
}
} else {
MessageAck ack = makeAckForAllDeliveredMessages(MessageAck.STANDARD_ACK_TYPE);
if (ack!=null) {
deliveredMessages.clear();
session.sendAck(ack);
}
}
}
}
deliveryingAcknowledgements.set(false);
}
} else if (isAutoAcknowledgeBatch()) {
ackLater(md, MessageAck.STANDARD_ACK_TYPE);
} else if (session.isClientAcknowledge()||session.isIndividualAcknowledge()) {
boolean messageUnackedByConsumer = false;
synchronized (deliveredMessages) {
messageUnackedByConsumer = deliveredMessages.contains(md);
}
if (messageUnackedByConsumer) {
ackLater(md, MessageAck.DELIVERED_ACK_TYPE);
}
}
else {
throw new IllegalStateException("Invalid session state.");
}
}
}
apollo 消息分发源代码分析的更多相关文章
- kafka消息分发策略分析
当我们使用kafka向指定Topic发送消息时,如果该Topic具有多个partition,无论消费者有多少,最终都会保证一个partition内的消息只会被一个Consumer group中的一个C ...
- Memcached源代码分析 - Memcached源代码分析之消息回应(3)
文章列表: <Memcached源代码分析 - Memcached源代码分析之基于Libevent的网络模型(1)> <Memcached源代码分析 - Memcached源代码分析 ...
- RTMPdump(libRTMP) 源代码分析 10: 处理各种消息(Message)
===================================================== RTMPdump(libRTMP) 源代码分析系列文章: RTMPdump 源代码分析 1: ...
- RTMPdump(libRTMP) 源代码分析 9: 接收消息(Message)(接收视音频数据)
===================================================== RTMPdump(libRTMP) 源代码分析系列文章: RTMPdump 源代码分析 1: ...
- RTMPdump(libRTMP) 源代码分析 8: 发送消息(Message)
===================================================== RTMPdump(libRTMP) 源代码分析系列文章: RTMPdump 源代码分析 1: ...
- Hadoop源代码分析
http://wenku.baidu.com/link?url=R-QoZXhc918qoO0BX6eXI9_uPU75whF62vFFUBIR-7c5XAYUVxDRX5Rs6QZR9hrBnUdM ...
- Android应用程序进程启动过程的源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址: http://blog.csdn.net/luoshengyang/article/details/6747696 Android 应用程序框架层创 ...
- Android应用程序绑定服务(bindService)的过程源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6745181 Android应用程序组件Serv ...
- Android应用程序启动过程源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6689748 前文简要介绍了Android应用程 ...
随机推荐
- oracle 多表连接查询
一.内连接(inner join (可简写为join)) 内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接列的列值. 1.等值连接:在连接条件中使用等于号(=)运算符比较被连接列的 ...
- Leetcode 473.火柴拼正方形
火柴拼正方形 还记得童话<卖火柴的小女孩>吗?现在,你知道小女孩有多少根火柴,请找出一种能使用所有火柴拼成一个正方形的方法.不能折断火柴,可以把火柴连接起来,并且每根火柴都要用到. 输入为 ...
- 九度oj 题目1391:顺时针打印矩阵
题目描述: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2 ...
- mybatis分页方式对比
mybatis有两种分页方法(转自:http://blog.csdn.net/leozhou13/article/details/50394242) 1.内存分页,也就是假分页.本质是查出所有的数据然 ...
- UITabBarController支持旋转
1.默认的UITabBarController不支持四个方向,但可以给UITabBarController增加一个类别,实现旋转:具体做法: 在工程添加一个.h和.m文件如下: //Rotation. ...
- base642photo
/** * pic to base64Str * @param path 读取路径 * @return */ public static String GetIm ...
- Mondriaan's Dream(poj 2411)
题意:在n*m的方格里铺1*2的骨牌,有多少种方案 /* 第一次做插头DP,感觉和状压差不多. 这道题是利用上一行的状态来更新下一行的状态. 1代表上一行这个位置填了一个竖的(即本行可以填): 0代表 ...
- 洛谷 P 1514 引水入城==Codevs 1066
题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形,如上图所示,其中每个格子都代表一座城市,每座城市都有一个海拔高度. ...
- 以iphone6plus 为标准单位是px的页面 在运行时转换为rem
在页面中引入以下代码,把样式中带px单位的样式放到本页面中的<style>标签中 /** * Created by Administrator on 2017-03-14. */ /*** ...
- linux 头文件以及库的路径
原来在编译的时候可以指定执行时去哪里找需要的lib文件,长知识了 本文详细介绍了Linux 下gcc头文件指定方法,以及搜索路径顺序的问题.另外,还总结了,gcc动态链接的方法以及路径指定,同样也讨论 ...