返回错误?但是有什么错误? 500?
是的,返回错误。从您的微服务返回错误并没有错。如果您的数据库出现故障,通常“500 Internal Server Error”是正确的错误。这是 Rest API 的标准行为。
但是微服务架构不是应该避免这种类型的吗?
耦合?我们应该让系统更松耦合吗?
我认为这里存在混淆。微服务与自己的数据库通信不被视为耦合。 Micro-service-A 正在使用其获得的数据库 micro-service-A-database 被视为一个逻辑单元或垂直。如果没有它的数据库,微服务 A 就没有多大用处,反之亦然。这完全没问题,您可以以与标准 WebApplication 类似的方式查看它的前端、后端(类似于您的服务)和数据库。应避免不同微服务之间的耦合。例如,微服务 A 不应与微服务 B 或微服务 C 紧密耦合。每个微服务都应该是原子的,并且尽可能独立,但不能独立于其数据库、缓存或类似的东西。您可以将数据库视为它的逻辑部分。
微服务是否应将数据保存在本地文件或队列中?
重试插入数据库?
不,预计数据库可能会失败,或者至少您还必须处理该选项。从用户的角度来看,您只会返回错误代码 500。至少在大多数情况下,这将是预期的行为。在某些特殊情况下,您希望不惜一切代价保存数据而不是因为该请求而丢失数据(也有一些方法可以处理这种情况)。
但是用户呢?
如果是标准网络用户,他会重试几次,如果问题仍然存在,则可能稍后再试(此处返回错误 500 没有任何问题)。如果用户的意思是另一个微服务正在执行调用,那么调用者微服务必须预期会发生故障。现在这取决于你在这里做什么?假设微服务 A 正在使用 Http 请求调用微服务 B:
-
Get Call:这里你可以在微服务A中建立重试策略,如果微服务B在重试后返回500,你可以向调用微服务B的用户返回错误.
-
Post/Put/Patch Call:您也可以在此处尝试与 Get Calls 类似的操作,但前提是涉及 1 项服务。如果您有微服务-A 调用微服务-B,然后是微服务-C,并且如果一个调用成功(保存了一些数据)而另一个调用失败,则必须考虑 Sagas(如果操作应该是事务性的) .
想象一下事件总线崩溃......如果是这样,消费者也会崩溃
在微服务中。
如果您的本地微服务数据库崩溃,那么所有其他渠道也应该崩溃。如果您无法将实体保存在本地微服务数据库中,为什么还要进一步执行诸如将消息发布到队列之类的操作?您的数据/实体的真实来源是数据库(至少在大多数情况下)。因此,如果数据库失败,您应该抛出异常并向调用者/用户返回错误。
如果 db insert 发生,生产者无法将事件发送到事件
总线....所以数据丢失了?生产者也应将数据保存在本地
重试存储?
因此,如果您将数据/实体保存在数据库中并且队列不可用,您可以简单地将消息/事件保存到数据库中的表中,然后在队列启动时发布消息/事件,并且再次运行。实际上,在这种情况下,这是一种非常常见的模式。例如,您的实现可能是事务性的:
- 将实体保存到其表中并
- 将事件/消息保存到事件表。这样,如果一个人失败了
操作将被回滚。
您可以让后台工作人员(取决于您用于后端的技术)以异步方式将消息发布到队列中。