我有两个申请,如下所述:
我的要求,我需要通过Spring启动应用程序提供不同的用户查询,Spring应用程序将该查询发送到消息队列,并在spout中使用。一旦喷口和螺栓处理请求,就会再次从螺栓中发布消息。 Bolt的响应在Spring引导(消费者)处理,并回复用户请求。典型如下所示:
为了服务于同一个请求,我现在正在缓存延迟结果对象(我为每个发送到拓扑的消息设置了一个reqID,我还维护了一个密钥,值对),当消息到达时我解析请求ID并将结果设置为defferedResult(我知道这是一个糟糕的设计,如何解决这个问题?)。
如何在这种情况下继续将响应提供回同一请求,其中从拓扑接收的消息顺序不是顺序的(因为每个请求都是进程需要自己的时间,而生成器bolt将触发响应,如同当它收到一个)。
我有点坚持这种设计,无法继续前进。
//Controller
public DeferredResult<ResponseEntity<?>> process(//someinput) {
DeferredResult<ResponseEntity<?>> result = new DeferredResult<>(config.getTimeout());
CompletableFuture<String> serviceResponse = service.processAsync(inputSource);
serviceResponse.whenComplete((response, exception) -> {
if (!ObjectUtils.isEmpty(exception))
result.setErrorResult(//error);
else
result.setResult(//complete);
});
return result;
}
//In Service
public CompletableFuture processAsync(//input){
producer.send(input);
CompletableFuture result = new CompletableFuture();
//consumer has a listener as shown below
// **I want to avoid below line, how can I redesign this**
map.put(id, result);
return result;
}
//in same service, a listener is present for consumer for reading the messages
consumerListener(Message msg){
int reqID = msg.getRequestID();
map.get(reqID).complete(msg.getData);
}
如上所示,只要收到消息,我就会获得completableFuture 对象并设置结果,它通常会调用defferred结果 对象并将响应返回给用户。
答案 0 :(得分:0)
如何在这种情况下继续将响应提供回同一请求,其中从拓扑接收的消息顺序不是顺序的(因为每个请求都是进程需要自己的时间,而生成器bolt将触发响应,如同当它收到一个)。
听起来您正在寻找Correlation Identifier消息传递模式。大致来说,您计算/创建一个附加到发送到脉冲星的消息的标识符,并安排Heron将该标识符从它接收的请求复制到它发送的响应。
因此,当您的Spring Boot组件在步骤5中使用来自脉冲星的消息时,您将相关ID与正确的http请求相匹配,并返回结果。
据我所知,使用原始的requestId()作为您的相关标识符应该没问题。
为了服务于同一个请求,我现在正在缓存延迟结果对象(我为每个发送到拓扑的消息设置了一个reqID,我还维护了一个密钥,值对),当消息到达时我解析请求id并将结果设置为defferedResult(我知道这是一个糟糕的设计,如何解决这个问题?)。
最终,你可能会在某种程度上这样做;也就是说,步骤5中的消费者将使用相关ID来查找由生产者存储的某物。试图将原始请求传递到四个不同的流程边界可能会以泪流满面。
更通用的形式是在地图中存储回调而不是CompletableFuture
;但在这种情况下,回调可能只是完成未来。
我想在设计中仔细检查一件事:您希望确保步骤5中的消费者在消息到达之前看到它应该使用的未来。换句话说,在某个地方应该有一个发生前的内存屏障,以确保步骤5中的地图查找不会失败。