java - 如何实现类似阻塞队列的SQL机制

标签 java spring postgresql

我的程序是一个通知服务,它基本上接收http请求(客户端发送通知)并将它们转发到设备。

我希望它按以下方式工作:

  1. 接收客户通知请求
  2. 将其保存到数据库(是的,我需要这一步,它是强制性的)
  3. 异步线程监视数据库中的新请求
  4. 异步线程将它们转发到目的地(设备)。

在这种情况下,程序可以在步骤 2) 后立即发送客户端确认。 因此,无需等待目的地响应(设备响应时间可能太长)。

如果我将客户端通知存储在内存中,我将使用 BlockingQueue。但我需要将我的通知保留在数据库中。另外,我无法使用消息队列,因为客户端希望休息端点发送通知。

帮我设计出这样一个机制的架构。

PS 在 Java、Postgresql 中

最佳答案

以下是一些可以得出解决方案的想法:

  1. 可能必须执行第 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/

    相关文章:

    java - spring 4.2 应用程序事件使用 Spring MVC 触发两次,为什么?

    postgresql - 没有更新/删除的死元组

    java - 友好的 URL 映射问题 - Java Spring

    java - 如何使用基于电子邮件地址的用户名对浏览器进行基本身份验证?

    java.util.Scanner 没有产生正确的结果

    html - thymeleaf : How to get first element of list without iterating?

    Java bean 持久化模式

    java - Spring 批处理 : How do I return custom exit code on invalid record with exception in spring batch

    python - postgresql 中 "TEXT"数据类型的最大大小

    PostgreSQL 时区转换