spring - 带有内部消息队列的前端 REST API?

标签 spring rest tomcat kubernetes rabbitmq

我创建了一个 REST API - 简而言之,我的客户点击了一个特定的 URL,她得到了一个 JSON 响应。

在内部,当 URL 被点击时,一个相当复杂的过程开始了,并且在使用微服务架构时涉及到各种服务。

我观察到一些性能瓶颈并决定切换到消息队列系统。这个想法是,现在,一旦用户点击 URL,就会在内部消息队列上发布一个请求,等待它被使用。该消费者将处理并发布回队列,这将发生很多次,直到最终,为用户提供服务的同一节点将收到处理后的响应以传递给用户。

现在正在使用异步“即发即弃”模式。但我的问题是,一旦处理的结果返回并且没有阻塞(即它可以处理多个请求直到收到响应),为特定人提供服务的节点如何记住它正在为谁服务?如果有什么不同的话,我的堆栈看起来有点像这样:TomCat、Spring、Kubernetes 和 RabbitMQ。

总而言之,请求节点(其工作是向队列中推送项目)如何与请求 JSON 响应(即客户端正在等待 JSON 响应)的客户端保持开放连接并接收返回的数据正确的客户?

最佳答案

根据您对客户端的控制程度,您有几个不同的场景。

如果无法更改客户端行为,您将不得不保持 session 打开,直到请求未被完全处理。这可以通过使用一个工作池( future /协程、线程或进程)来实现,其中每个工作人员为给定的请求保持 session 打开。

这种方法几乎没有缺点,我会保留它作为最后的手段。首先,您将只能处理与您的池大小成比例的有限数量的并发请求。最后,由于您的处理在队列后面,您的前端将无法估计完成任务需要多长时间。这意味着您将不得不处理容易失败的长时间 session (如果用户放弃了怎么办?)。

如果可以更改客户端行为,最常见的方法是使用完全异步的流程。当客户端发起一个请求时,它被放置在队列中并返回一个任务标识符。客户端可以使用给定的 TaskId 来轮询状态更新。每次客户请求更新任务时,您只需检查它是否已完成并做出相应的响应。当任务仍在进行中时,一种常见的模式是让前端在重试之前将估计的时间返回给客户端。这允许您的服务器控制客户端轮询的频率。如果您的架构支持它,您可以加倍努力并提供有关进度的信息。

任务进行中的响应示例:

{"status": "in_progress",
 "retry_after_seconds": 30,
 "progress": "30%"}

更复杂但更优雅的解决方案是使用 HTTP 回调。简而言之,当客户端请求新任务时,它会提供一个元组(URL,方法),服务器可以使用它来表示处理完成。然后它等待服务器将信号发送到给定的 URL。可以看到更好的解释here .在大多数情况下,这种解决方案是多余的。但我认为值得一提。

关于spring - 带有内部消息队列的前端 REST API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53525239/

相关文章:

tomcat 中的 Java Web 应用程序会定期卡住

spring - @Cacheable 标签在 Spring 上的 JUnit 测试期间似乎被忽略

spring - spring Controller 中的单元测试响应状态代码

javascript - 安全 HTTP 基本身份验证

rest - 应用程序服务调用的正确 RESTful URL 约定?

tomcat - 如何将Tomcat的IP地址和端口号更改为某个url

spring - 无法在Spring Data项目中加载资源

java - Spring 事务 REQUIRED 与 REQUIRES_NEW : Rollback Transaction

java - JAX-RS RESTful 服务和永久 Oracle 连接

java - 在使用 Tomcat 的 Eclipse 动态 Web 项目中将文本文件放在哪里?