请教消息队列的选择

3 天前
daimaosix  daimaosix
目前正在调研 Kafka 和 RabbitMQ ,项目需要给每个客户创建一个主题,该主题下客户所有的设备作为消费者,每台设备独立消费并确认消费结果,客户端和服务端均使用 Rust 编写,发现 Kafka 对于消费结果确认似乎不如 RabbitMQ 方便,可能需要自己实现。但 Kafka 性能要比 RabbitMQ 优异,所以就不太清楚选择哪一个比较合适。
另外对于负载能力,这个项目是安全相关,如果攻击量比较大,那可能对于消息队列而言并发就比较大,暂时预估 3000-5000 这样子吧。消息不需要持久存储,属于消费者实时快速消费完可以直接删除。
有经验的老哥多谢指导!
502 次点击
所在节点   程序员  程序员
10 条回复
keakon
keakon
3 天前
RabbitMQ 在低负载(< 30 MB/s )下延迟更低,资源开销、易用性和稳定性都更好。但是如果 topics 过多,例如上千,就会显著影响性能。当然你也可以多部署几个 RabbitMQ ,将不同客户打散到不同的实例,让每个实例的 topics 减少。
Kafka 的内存开销很大(毕竟 Java ),稳定性不够好,但是 topics 增长基本不影响性能。
souryou
souryou
3 天前
恰巧两个都用过,不过没在 rust 下用过

1.对于这个 '发现 Kafka 对于消费结果确认似乎不如 RabbitMQ 方便' 我没有太理解不方便指具体是哪方面,我看 [demo]( https://github.com/kafka-rust/kafka-rust/blob/master/examples/example-consume.rs#L47) 中没有太复杂

2. 你所提到的 3000-5000 负载远远没有达到他俩的正常运行阈值,所以这点应该没啥问题,这个量再 X10 的话推荐 Kafka

3. 'Kafka 性能要比 RabbitMQ 优异' ,这个也得结合具体项目来看,按照你说的极端情况在 5k 左右的话,他俩哪个都没有问题

4. 其他方面还要根据项目、人员使用熟练度来选

**注意 ** : 一个客户一个主题,客户下设备数量需要考虑

kafka 根据 consumer 多于 partition 数量会闲置,rabbit 默认是轮训
daimaosix
daimaosix
3 天前
@keakon 如果只有一个消费者只创建一个主题,那将所有用户的客户端全部作为消费者来消费这一个主题,让消费者来根据消息内容中的用户 ID 来决定是否消费,这样是否可行呢?
daimaosix
daimaosix
3 天前
@souryou
1.因为 Kafka 消费者对于消息的消费成功与否根据偏移量来进行,而 RabbitMQ 原生就支持从队列中确认消息是否未消费或者已消费或者忽略消费,这种状态控制比较明确,而 Kafka 需要在程序中实现消息消费状态的计数等。

感谢最后提及的,客户下的消费者这个没办法控制,可能多大几十个,也有可能只有几个这样子,具体按照用户的服务器数量来
keakon
keakon
3 天前
@daimaosix 假设你有 1000 个 topics ,5000 个客户端。
原方案是某个 topic 收到消息,只会通知 5 个客户端来获取消息。
你的方案会导致 5000 个客户端来获取消息,然后大部分丢弃掉。
性能差异可想而知。

此外,RabbitMQ 默认是不允许同一条消息被多个消费者并发消费的,需要使用 Fanout Exchange 。此时每个消费者都是一个单独的队列,即变成 5000 条队列,发布消息的开销会增大 5000 倍。
souryou
souryou
3 天前
@daimaosix
1. 它俩的确认应该都不用在编程逻辑中处理,需要处理的就是消息去重逻辑,避免二次消费

2. 对于 consumer 数量问题,是不是可以考虑每个客户对应一个 agent 来消费来自这个客户的 topic ,然后在根据服务器 ip 、mac 等唯一参数,进一步划分二级 topic ;或者根据客户 ID 加上服务器 ID 直接细化 topic ,但是每引进一个中间(件)过程,系统的鲁棒性就多一次考验。


将所有用户的客户端全部作为消费者来消费这一个主题,让消费者来根据消息内容中的用户 ID 来决定是否消费,这样是否可行呢?

不建议这么搞。这个无用处理有点儿多(每个机器处理客户机器数量 n 的消息,但是有 n-1 是忽略的),而且属于广播模式,恰巧应该消费的机器由于网络或真实掉线,消息容易丢失。
daimaosix
daimaosix
3 天前
@keakon
@souryou
感谢两位老哥的宝贵建议。我现在考虑使用 RabbitMQ 的路由模式,为每个用户的消费者指定唯一的路由键,确保消息只被需要的消费者消费,因为业务逻辑不是很复杂,能确保消息抵达对应用户的消费者即可。

但如果消费者过多,比如超过 1000+,这可能就需要分片或集群了....
flmn
flmn
2 天前
你这个场景,这俩都不合适啊。

MQTT 比较合适。
daimaosix
daimaosix
2 天前
@flmn 为啥啊大哥
flmn
flmn
2 天前
@daimaosix 因为你提到了设备,而 MQTT 是物联网消息队列/订阅事实上的标准,我感觉很适合你的场景,你调研一下

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1119476

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX