1. 分布式环境下,强一致性难达到
MNS是基于阿里云飞天分布式平台上的消息服务,具有高并发、高可扩展等优点,别看大家平常只是向一个URL地址收发消息,但是MNS后端却是多台Message Server为大家提供服务;各个Message Server会将用户发送的消息数据持久化,同时在内存中维护了实时的计数信息,并且定期上报计数信息给Meta管理节点(如图1),Meta管理节点负责管理并持久化Message Server上报的计数数据。用户调用GetQueueAttributes接口获取的队列属性数据就是从Meta管理节点中获取到的,所以当您高并发调用消息API时,由于各个Message Server上报数据的先后关系,您获得的消息计数值就无法做到精确。特别是当某台Message Server机器发生异常或者failover时,其精确计数信息可能无法及时上报至Meta管理节点;而Message Server在恢复之后,会将Meta管理节点中持久化的计数数据load到本地的内存中,这样也是造成计数无法做到准确的重要原因。
(图1)
2. 过期消息
在MNS中,队列中消息是有过期时间的,如果长时间消息未消费,则消息将变为过期消息,将会被MNS系统回收掉。为了保证消息消费的效率,MNS并不会立刻对过期消息进行回收,只是在保证过期消息不会被用户消费到的前提下,MessageServer后台会有专门的GC模块负责定期回收各个队列的过期消息并修改消息计数(如图2)。这就造成了如果存在过期消息,在消息未被回收之前,过期消息还是会体现在消息计数中。
(图2)
以上两点就是MNS目前遇到消息计数不精确的主要问题;同时国外的云计算A公司在其队列服务中提供的也是近似值(如:ApproximateNumberOfMessages)。应用程序如果强依赖于队列消息计数,并不是分布式高并发环境下最佳选择,用户只需要通过长轮询ReceiveMessage接口获取数据即可,如果队列为空,则ReceiveMessage请求将会在MNS端挂起一段时间,期间有任何消息进入队列,挂起的请求都将立刻返回最新的消息;而MNS在队列属性中提供消息计数的初衷主要是提供一个能够大致反映队列堆积情况的,特别当队列计数接入了云监控之后,用户可以轻松通过设置云监控报警来实现队列堆积情况预警;同时在针对消息积压情况进行收费时,我们也是充分考虑到了消息计数可能造成的偏差,目前在MNS的收费用户当中,由于消息积压情况导致收费的并不多,而且也确确实实是堆积了大量消息。但是鉴于计数问题是MNS用户反映最多的问题,所以MNS后续将会推出队列计数最终一致性保障机制。
大家如果对本文有任何疑问,都可以在帖子中提出,小编会第一时间回复,感谢大家对MNS的支持!我们会不断提升MNS的用户体验,推出更多符合用户使用场景的功能!