RabbitMQ - 消息超时设置/设置消息的生存(过期)时间TTL

11 篇文章 0 订阅

背景:

         当消息发布方一直在推送消息,而消息的订阅方一直未订阅,且恰巧接收消息的队列未设置delete when unused。则消息会一直堆积在队列里面,长此以往难免会出现问题。那么有什么方法可以避免这种问题发生呢?

 

解决方案:

         两种方法:

                (1)在创建队列的时候,为队列进行“当没有消费者的时候,自动删除队列,即:auto-delete”。

                (2)为存入队列的消息设置一个过期时间,即若消息超过一定的时间还没有被消费者进行消费,则自动清理掉该条消息。(该种方式其实存在一定的缺陷,那就是当消费者消费能力不足时,即未能及时的从队列里取走该条消息,会造成消息的丢失。)

         这里我主要是介绍第二种方法,即给消息设置过期时间TTL。

什么是消息的TTL?

TTL全称Time To Live,即生存时间。消息的TTL也就是消息的生存时间。在RabbitMQ中设置TTL的手法有两种:

  • 第一种是声明队列的时候,在队列的属性中设置TTL,这样该队列中的消息都会有相同的有效期。
  • 第二种是发送消息时给消息设置属性,可以为每条消息都设置不同的TTL。

如果两者都进行了设置,则生存时间取两者中最小的那一个。

 

代码展示:

          首先展示一下在声明队列的时候,设置消息TTL。其实是作为参数【"x-message-ttl"】传进去的。

          (1)C++代码

//...

void AMQPQueue::Declare(int ttlTime)
{
	//...

	sendDeclareCommand();
}

void AMQPQueue::sendDeclareCommand() {
	if (!name.size())
		throw AMQPException("the queue must to have the name");

	amqp_bytes_t queue_name = amqp_cstring_bytes(name.c_str());

	/*
		amqp_basic_properties_t props;
		props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG;
		props.content_type = amqp_cstring_bytes("text/plain");
	*/
	amqp_table_t args;
	// 是否设置消息TTL
	if (0 != ttlTime)
	{
		args.num_entries = 1;
		amqp_table_entry_t_ pTable;
		pTable.key = amqp_cstring_bytes("x-message-ttl");
		pTable.value.kind = AMQP_FIELD_KIND_U16;
		pTable.value.value.u16 = ttlTime;
		args.entries = &pTable;
	}
	else
	{
		args.num_entries = 0;
		args.entries = NULL;
	}

	amqp_boolean_t exclusive =  (parms & AMQP_EXCLUSIVE)	? 1:0;
	amqp_boolean_t passive =    (parms & AMQP_PASSIVE)		? 1:0;
	amqp_boolean_t autodelete = (parms & AMQP_AUTODELETE)	? 1:0;
	amqp_boolean_t durable =    (parms & AMQP_DURABLE)		? 1:0;

	amqp_queue_declare_t s;
		s.ticket = 0;
		s.queue = queue_name;
		s.passive = passive;
		s.durable = durable;
		s.exclusive = exclusive;
		s.auto_delete = autodelete;
		s.nowait = 0;
		s.arguments = args;

	amqp_method_number_t method_ok = AMQP_QUEUE_DECLARE_OK_METHOD;
	amqp_rpc_reply_t res = amqp_simple_rpc(*cnn, channelNum, AMQP_QUEUE_DECLARE_METHOD, &method_ok , &s);

	AMQPBase::checkReply(&res);

	amqp_release_buffers(*cnn);
	char error_message [256];
	memset(error_message,0,256);

	if (res.reply_type == AMQP_RESPONSE_NONE) {
		throw AMQPException("error the QUEUE.DECLARE command, response none");
	}

	if (res.reply.id == AMQP_CHANNEL_CLOSE_METHOD) {
		amqp_channel_close_t * err = (amqp_channel_close_t *) res.reply.decoded;

		int c_id = 	(int) err->class_id;
		sprintf( error_message, "server error %u, message '%s' class=%d method=%u ", err->reply_code, (char*)err->reply_text.bytes, c_id,err->method_id);
		opened=0;

		throw AMQPException(&res);
	} else if (res.reply.id == AMQP_QUEUE_DECLARE_OK_METHOD) {
			amqp_queue_declare_ok_t* data = (amqp_queue_declare_ok_t*) res.reply.decoded;
			count = data->message_count;
	} else {
		sprintf( error_message, "error the Declare command  receive method=%d", res.reply.id);
		throw AMQPException(error_message);
	}
}

          (2)Go代码

// 在队列的属性中设置TTL,这样该队列中的所有消息都会有相同的有效期
var (
	args = make(map[string]interface{})
)
args["x-message-ttl"] = 60000
_, err = channel.QueueDeclare(
	que,   // name
	false, // durable
	true,  // delete when unused
	false, // exclusive
	false, // no-wait(是否阻塞处理)
	args)  // arguments
if err != nil {
	errMsg := fmt.Sprintf("Failed to open declare Queue! err = %v", err)
	return nil, nil, errors.New(errMsg)
}

 

          其次展示一下在发送消息的时候,设置消息TTL。(下面仅展示Go代码,C++的实现可自行实现一下加深理解,原理都是相通的。)

if err := channel.Publish(
	exchange, // exchange
	routKey,  // routing key
	false,    // mandatory
	false,
	amqp.Publishing{
		Expiration: "60000" // 设置消息的TTL为60秒  <发送消息时给消息设置属性,可以为每条消息设置不同的TTL>
		ContentType: "text/plain",
		Body:        []byte(body),
		Timestamp:   time.Now(),
	},
); err != nil {
	errMsg := fmt.Sprintf("Failed to msg Publish! err = %v", err)
	return errors.New(errMsg)
}
return nil

 

检验:

          在RabbitMQ网页中可以看Queue的Features字段若有“TTL”标识,则代表此队列设置TTL成功。

          点进去后在Details面板下可以看到具体的TTL时间。

 

后言:

         如果觉得此文章还算有所帮助的话,就三连支持一下吧(* ̄︶ ̄)。后面的分享更精彩喔~~

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值