队列关闭时该怎么办?

时间:2018-01-11 14:37:13

标签: architecture queue message-queue microservices amazon-sqs

我有2个微服务,AB。当A收到来自用户的请求时,会对其进行处理(将某些内容存储在数据库中),并将消息发送到B读取的队列。

如果队列已关闭,我最初的想法是让整个请求崩溃,回滚并向用户显示错误,要求稍后再试。这是一种不好的做法吗?

将消息存储在标记为A的{​​{1}}数据库中并且稍后当队列再次启动时有一个作业发送它会更好吗?还是过度工程?

编辑:对NOT_SENT的请求需要同步,因此用户知道其结果,但他们需要知道{{1}的结果处理消息,因此它可以是异步的。

5 个答案:

答案 0 :(得分:2)

您正在数据库中创建冗余队列。如果队列不可靠,您可以创建其中的几个,但使用数据库设计自己的队列是重复工作。如果确实需要两个队列来实现冗余,请创建两个队列。它可以兼作医院队列,因为可能需要处理主队列中的处理失败(具有相同的重试语义)。

答案 1 :(得分:2)

你问一个关于一个非常抽象的例子的具体问题。在实践中,这些问题很少产生有用的结果。

话虽如此,如果您的系统不处于可以以可靠和确定的方式处理请求的状态(例如,队列组件不起作用),那么您应该阻止所有依赖于该功能的请求(即使用503 - 服务不可用)。实际上,如果这是一个队列问题或数据库问题并不重要 - 除非所有部分都正常运行,否则服务无法执行其行为,因此请事先告诉客户。如果您的可靠性需要更高,您将不得不在设计上投入更多时间以获得更高的可靠性。

答案 2 :(得分:1)

是的,这取决于您的操作是否是原子操作(因此用户需要立即反馈),或者仅仅是后台处理工作,正如Nicolas指出的那样。 我只想补充一点,您可以考虑实施断路器模式,在向用户报告失败之前重试几次,或者根据您的要求将消息保持为NOT_SENT。

答案 3 :(得分:1)

  

我有2个微服务,A和B.当A接收到来自用户的请求时,它会被处理(在数据库中存储一些东西),并且消息被发送到由B读取的队列。

确定。让我们假设某些东西被处理并保存到数据库中=产生了一些副作用。

  

如果队列已关闭,我最初的想法是让整个请求失效并向用户显示错误,要求稍后再试。这是一种不好的做法吗?

但是你需要撤消第一步(上面讨论的那一步),然后才会失败客户端的请求!您有两种选择:

  • 将副作用和队列添加到事务中;这仅适用于可撤消的副作用(即删除文件不可撤消,除非它只是移动到垃圾箱)。当第一步必须同步处理时,应使用此解决方案。

  • 将请求添加到队列并稍后处理,第一个异步步骤是微服务A.如果添加到队列失败则请求失败。此解决方案比第一个解决方案更具可扩展性。

答案 4 :(得分:0)

我觉得这取决于用户是否应该根据他们的第一个动作对系统做任何事情,或者他们希望它立即反映在其他地方。

正如一个例子,因为您通常在会话中管理此信息而不是写入数据库:如果第一个操作是“将产品添加到购物车”然后用户继续尝试检查,我认为整个请求应该提前失败,而不是保存一个状态,当它稍后失败并且最初似乎正常工作时可以被视为“错误”。

另一个例子可能是获取某种收据或代码,然后他们想要用来离线兑换某些东西,但是负责这样做的人并不认为代码是有效的,而你又有这种思维状态另一个是错的,因为他们有不同的数据。

现在,如果您只是想收集一些数据并在不同的服务中处理它,可能最好将其保存为未发送,而不是强迫用户多次发送数据或稍后返回。

有关您的要求或域的更多详细信息,您可能会更好地猜测哪个选项是一个好的解决方案,因为它们可以解决不同的问题。