本文章将进入mosquitto源码,介绍几个与客户端相关的时间变量,初探这些变量的含义。由于能力有限,如有错误,欢迎批评指正。注意:以下主要针对Durable Connection而言。
- keepalive:对应于mosquitto.conf中的max_keepalive配置选项,表示broker与client(桥模式的client除外)之间交互时,报文的最大有效时间,这个时间也可以成为保活时间,目前在mosquitto的实现中,保活时间被放大到1.5倍。客户端超时后,连接将会断开。
- persistent_client_expiration:Durable Connection超时时间。
- session_expiry_interval:连接会话间隔时间。存在两个特殊值:0表示立即删除会话,UINT32_MAX表示永不删除会话。在MQTT V5版本以前,本值默认为UINT32_MAX。
以上几个变量之间的关系如下:
1、keepalive大于0,如果是,则如果客户端在1.5倍的时间内未发送报文,那么broker将主动断开与该客户端的连接。keepalive等于0时表示永远存活。桥模式下的客户端不受本参数影响,即:永不超时。
if(!(context->keepalive)
|| context->bridge
|| now - context->last_msg_in <= (time_t)(context->keepalive)*3/2){
....
} else {
/* Client has exceeded keepalive*1.5 */
do_disconnect(db, context, MOSQ_ERR_KEEPALIVE);
}
2、连接断开之后,mosquitto将检查连接会话的间隔时间(session_expiry_interval)。如果该变量等于0,那么直接删除该clientid。如果该变量等于UINT32_MAX,则该clientid表示的会话信息将永久保存。如果大于0,且不等于UINT32_MAX,进入下个步骤。
if(context->sock == INVALID_SOCKET
&& context->session_expiry_interval > 0
&& context->session_expiry_interval != UINT32_MAX)
{
/* This is a persistent client, check to see if the
* last time it connected was longer than
* persistent_client_expiration seconds ago. If so,
* expire it and clean up.
*/
if(now > context->session_expiry_time) {
...
G_CLIENTS_EXPIRED_INC();
context->session_expiry_interval = 0;
mosquitto__set_state(context, mosq_cs_expiring);
do_disconnect(db, context, MOSQ_ERR_SUCCESS);
}
}
3、如果persistent_client_expiration大于0,mosquitto根据的persistent_client_expiration值与session_expiry_interval进行比较,选择其中最小的值作为该会话的超时时间;如果persistent_client_expiration值未配置,那么将使用session_expiry_interval的值作为超时时间,并把该会话的信息添加到过期列表中。
item->context->session_expiry_time = time(NULL);
if(db->config->persistent_client_expiration == 0
|| db->config->persistent_client_expiration < item->context->session_expiry_interval)
{
item->context->session_expiry_time += item->context->session_expiry_interval;
} else {
item->context->session_expiry_time += db->config->persistent_client_expiration;
}
context->expiry_list_item = item;
DL_INSERT_INORDER(expiry_list, item, session_expiry__cmp);
...
4、该客户端未在超时时间内进行重连,broker会将客户端的会话信息删除回收。由于broker中该会话信息已经被删除,因此假设客户端断开之后,broker在该topic上接收到了很多消息,那么这些消息以后也将不会再发送给该客户端。对于永久存活的客户端,Qos大于0的消息在后续客户端重连的时候,这些客户端仍然能够接收到那些消息。