我必须创建两个服务,让我们调用服务A和服务B。A需要向B发送消息并且不期望得到响应。考虑到消息数量并不大,比如每秒最多 5 条, 设计此类系统的最佳方法是什么。
方法1)服务A -> 消息代理(ActiveMQ队列) -> 服务B
方法2)服务A(java队列+Rest Call)->服务B
服务A将消息放入JAVA阻塞队列中。另一个线程正在主动检查队列中是否有新消息,如果收到消息,则会向服务 B 发出 http Rest 调用。
方法(2)不会阻塞服务A原有的消息承载线程,可以继续工作,也不需要实现消息代理,系统复杂度较低。但它会消耗一些内存,因为消息存储在服务 A 内部的队列中。
我认为,当服务A不需要等待服务B的响应时,最好用RabbitMq/SQS/Kafka这样的队列来解耦它们。
优点:
减少爆炸半径:在生产中减少系统之间的耦合,减少系统之间传播的运行时故障。例如如果服务1直接调用服务2,如果服务2宕机或者api中的bug引发错误,服务1也会受到影响。由于服务 1 不依赖于服务 2 的响应,因此拥有队列可以使服务 1 独立。像 SQS/Kafka 这样的队列是稳定的,不会在集成点造成故障。
更轻松的开发:开发人员在实现逻辑时可以只专注于服务1/服务2。在服务2中,人们总是可以模拟队列中的消息。
独立扩展和降低成本:如果服务 1 很关键并且以 100 qps 的速度生成消息,则服务 2 不需要以相同的速率处理。由于消息将存储在队列中,并且服务 2 可以按照自己的节奏处理它。
容错:当多个worker处理队列时,当其中一个worker读取消息时,消息将被隐藏。在超时时间内,如果worker没有响应处理成功的消息,该消息将重新出现在队列中以供另一个worker处理。这会进行重试,并使服务 1 独立于服务 2 中的重试。