我的程序是一个通知服务,它基本上接收http请求(客户端发送通知)并将它们转发到设备。
我希望它按以下方式工作:
- 接收客户通知请求
- 将其保存到数据库(是的,我需要这一步,它是强制性的)
- 异步线程监视数据库中的新请求
- 异步线程将它们转发到目的地(设备)。
在这种情况下,程序可以在步骤 2) 后立即发送客户端确认。 因此,无需等待目的地响应(设备响应时间可能太长)。
如果我将客户端通知存储在内存中,我将使用 BlockingQueue。但我需要将我的通知保留在数据库中。另外,我无法使用消息队列,因为客户端希望休息端点发送通知。
帮我设计出这样一个机制的架构。
PS 在 Java、Postgresql 中
最佳答案
以下是一些可以得出解决方案的想法:
- 可能必须执行第 2 步,以确保请求持续存在,以便查询它。所以我们在这里讨论一些“数据模型”。 考虑到这一点,如果您“在第 2 步之后立即”发送”确认信息 - 如果稍后您想对此数据执行某些操作(例如,将其发送到某个地方)并且此操作没有成功,该怎么办?你把它存储在磁盘上吗?如果磁盘已满会发生什么?
最重要的问题是在这种情况下您的数据模型(在数据库中)会发生什么?数据库中的条目是否仍然存在,或者整个“逻辑”操作已经失败?您应该弄清楚这一点,具体取决于实际系统,答案可能会有所不同。
最“严格”的解决方案将按以下(示意性)方式使用事务:
tr = openTransaction()
try {
saveRequestIntoDB(data);
forwardToDestination(data);
tr.commit();
} catch(SomeException ex) {
tr.rollback();
}
采用这种设计,如果在“saveRequest”步骤中出现问题,那么什么也不会发生。如果数据存储在数据库中,但是 forwardToDestination
失败 - 那么事务将回滚并且记录不会存储在数据库中。
如果所有操作都成功 - 事务将被提交。
- 现在看起来您仍然可以使用第 4 步中的消息传递系统。发送消息可以很快,并且不会给整个请求增加任何显着的开销。
另一方面,好处也是显而易见的: - 谁听这些“通知”?如果您发送了一些内容,并且只有一项服务应该接收并处理该通知,您如何确保其他服务不会收到该通知?您将如何实现相反的情况 - 如果所有服务都应该收到通知并独立处理它怎么办?
这些设施已经由任何下降消息系统实现。
- 我不太明白这个说法:
I cannot use Message Queues, because clients want rest endpoints to send notifications.
由于整个流程都是由客户的请求发起的,所以我在这里没有看到任何矛盾。从rest端点调用的代码(毕竟是一个应该由您实现的逻辑入口点)可以调用数据库,持久化数据,然后发送通知...
关于java - 如何实现类似阻塞队列的SQL机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62245014/