public class QoS4SendDaemon
extends java.lang.Object
TCP理论上能从底层保证数据的可靠性,但应用层的代码和场景中存在网络本身和网络之外的各种不可靠性,
MobileIMSDK中的QoS送达保证机制,将加强TCP的可靠性,确保消息,无法从哪一个层面和维度,都会给
开发者提供两种结果:要么明确被送达(即收到ACK应答包,见
MessageQoSEvent.messagesBeReceived(String)
)、要行明确
未被送达(见MessageQoSEvent.messagesLost(ArrayList)
)
。从理论上,保证消息的百分百送达率。
一个有趣的问题:TCP协议为什么还需要消息送达保证机制?它不是可靠的吗?
是的,TCP是可靠的,但那是在底层协议这一层。但对于应用层来说,TCP并不能解决消息的百分百可靠性。
原因有可能是:
1)客户端意外崩溃导致TCP缓冲区消息丢失; 2)网络拥堵,导致TCP反复重传并指数退避,导致长时间无法送达的也应在送达超时时间内被判定为无法送 达(对于应用层来说tcp传的太慢,用户不可能等的了这么久,否则体验会很差); 3)中间路由故障,tcp本身是无法感知的,这种情况下tcp做传输重试也会出现2)中的情况,这也应算是事 实上的无法送达; 4)其它更多情况。
当前MobileIMSDK的QoS机制支持全部的C2C、C2S、S2C共3种消息交互场景下的消息送达质量保证.
本线程的启停,目前属于MobileIMSDK算法的一部分,暂时无需也不建议由应用层自行调用。
限定符和类型 | 字段和说明 |
---|---|
static int |
CHECH_INTERVAL
QoS质量保证线程心跳间隔(单位:毫秒),默认5000ms.
|
static int |
MESSAGES_JUST$NOW_TIME
“刚刚”发出的消息阀值定义(单位:毫秒),默认3000毫秒。
|
static int |
QOS_TRY_COUNT
一个包允许的最大重发次数,默认2次。
|
限定符和类型 | 方法和说明 |
---|---|
void |
clear()
清空缓存队列。
|
java.util.Observer |
getDebugObserver()
!
|
static QoS4SendDaemon |
getInstance() |
boolean |
isInit()
本类对象是否已补初始化过。
|
boolean |
isRunning()
线程是否正在运行中。
|
protected void |
notifyMessageLost(java.util.ArrayList<net.x52im.mobileimsdk.server.protocal.Protocal> lostMessages)
将未送达信息反馈给消息监听者。
|
void |
put(net.x52im.mobileimsdk.server.protocal.Protocal p)
推入一个消息包的指纹特征码.
|
void |
remove(java.lang.String fingerPrint)
移除一个消息包.
|
void |
setDebugObserver(java.util.Observer debugObserver)
!
|
int |
size()
队列大小.
|
void |
startup(boolean immediately)
启动线程。
|
void |
stop()
无条件中断本线程的运行。
|
public static final int CHECH_INTERVAL
间隔越短则为用户重发越即时,但将使得重复发送的可能性增大(因为可能在应答包尚在途中时就判定丢包了的错误情况) ,当然,即使真存在重复发送的可能也是无害的,因为MobileIMSDK的QoS机制本身就有防重能力。请根据您的应用所处 的网络延迟情况进行权衡,本参数为非关键参数,如无特殊情况则建议无需调整本参数。
public static final int MESSAGES_JUST$NOW_TIME
此阀值的作用在于:在QoS=true的情况下,一条刚刚发出的消息会同时保存到本类中的QoS保证队列,在接收方的应答包 还未被发出方收到时(已经发出但因为存在数十毫秒的网络延迟,应答包正在路上),恰好遇到本次QoS质量保证心跳间隔 的到来,因为之前的QoS队列罗辑是只要存在本队列中还未被去掉的包,就意味着是要重传的——那么此逻辑在我们本次讨论 的情况下就存在漏洞而导致没有必要的重传了。如果有本阀值存在,则即使刚刚发出的消息刚放到QoS队列就遇到QoS心跳 到来,则只要当前放入队列的时间小于或等于本值,就可以被认为是刚刚放入,那么也就避免被误重传了。
基于以上考虑,本值的定义,只要设定为大于一条消息的发出起到收到它应答包为止这样一个时间间隔即可(其实就相于 一个客户端到服务端的网络延迟时间4倍多一点点即可)。此处定为3秒其实是为了保守起见哦。
本参数将决定重传的即时性问题,即当MobileIMSDK判定消息未送达时,QoS首次重传的
响应时间为大于 MESSAGES_JUST$NOW_TIME
(即3000毫秒) 而 小于或等于 CHECH_INTERVAL
(即5000毫秒)。
public static final int QOS_TRY_COUNT
次数越多,则整个消息的可靠性越好,但在网络确实很烂的情况下可能会导致重传的泛滥而失去“即时”的意义。请根据网络 状况和应用体验来权衡设定,本参数为0表示不重传,建议使用1到5之间的数字。
public static QoS4SendDaemon getInstance()
protected void notifyMessageLost(java.util.ArrayList<net.x52im.mobileimsdk.server.protocal.Protocal> lostMessages)
lostMessages
- 已被判定为“消息未送达”的消息列表ClientCoreSDK.getMessageQoSEvent()
public void startup(boolean immediately)
无论本方法调用前线程是否已经在运行中,都会尝试首先调用 stop()
方法,以便确保线程被启动前是真正处
于停止状态,这也意味着可无害调用本方法。
本线程的启停,目前属于MobileIMSDK算法的一部分,暂时无需也不建议由应用层自行调用。
immediately
- true表示立即执行线程作业,否则直到 CHECH_INTERVAL
执行间隔的到来才进行首
次作业的执行public void stop()
本线程的启停,目前属于MobileIMSDK算法的一部分,暂时无需也不建议由应用层自行调用。
public boolean isRunning()
public boolean isInit()
init
。public void put(net.x52im.mobileimsdk.server.protocal.Protocal p)
p
- 原始消息协议包public void remove(java.lang.String fingerPrint)
此操作是在步异线程中完成,目的是尽一切可能避免可能存在的阻塞本类中的守护线程.
fingerPrint
- 消息包的特纹特征码(理论上是唯一的)public void clear()
调用此方法可以防止在APP不退出的情况下退出登陆MobileIMSDK时没有清除队列缓存,导致此时换用另一账号时发生数据交叉。
public int size()
HashMap.size()
public java.util.Observer getDebugObserver()
public void setDebugObserver(java.util.Observer debugObserver)
debugObserver
- DEBUG事件观察者