我在Spring有两个微服务。第一个,让我们称他为DataDeliverer从互联网收集一堆数据,他将这些数据作为json发送到第二个微服务,例如Receiver。发送按部分划分。零件数量是随机的。 Receiver和DataDeliver永远都不知道会有多少部分。接收器正在接收部件并使用Spring的注释@Async异步保存它们。这给我带来了问题,因为我必须知道发送已完成并且接收器已完成接收。
这一刻我想出来,如下: 添加java.util.Map,将object作为键,并将标志isFinished作为值。然后我会知道保存单个对象(部分)是否已完成。当DataDeliverer结束sendig数据时,他将发送有关它的信息。当Receiver获取此信息时,只需等待Map中的所有标志都显示所有对象都已保存。然后收集数据。您对此解决方案有何看法?我会很感激任何提示。 感谢
以下是现状的简单概述。不要介意java的正确性。这是伪java更容易显示问题。
public class DataDeliver {
public void sendData(List<Data> listWithRandomSize) {
List<Data> listToSend = new ArrayList<>();
int i = 0;
listWithRandomSize.forEach(data -> {
listToSend.add(data);
i++;
if (i%10 == 0) {
restTemplate.postForObject("http://receiver:8080/save/", listToSend);
listToSend = new ArrayList<>();
i = 0;
}
}
}
}
public class SomeReceiverService {
@Async
public void save(List<Data> partOfData) {
database.save(partOfData);
}
}
答案 0 :(得分:1)
在异步方法中,您可以返回类型为org.springframework.util.concurrent.ListenableFuture<T>
或使用Java8 java.util.concurrent.CompletableFuture<T>
的对象。该返回值由async方法立即返回,可用于注册回调/处理程序以确定失败和/或成功。
基本上你的组件应该是这样的
@Component
public class SomeService {
@Async
public CompletableFuture<String> someServiceMethod() {
// do something async
return CompletableFuture.completedFuture(someResult);
}
}
你的客户是这样的:
public class SomeClient {
@Autowired
private SomeService mSomeService;
public void someClientMethod() {
//Function to process result of async call
final Function<String, String> resultHandler = null;
mSomeService.someServiceMethod().thenApply(resultHandler);
}
}
请参阅async example on spring.io以获取完整参考。
根据您的示例代码,对SomeReceiverService.save
的每次调用都会返回一个新CompletableFuture
(实际上截至目前AsyncRestTemplate
似乎只支持ListenableFuture
- 您可能需要将它们转换为CompletableFuture
以从其加入功能中受益)您可以收集这些期货并等待它们全部完成:
List<CompletableFuture<Void>> allFutures = new ArrayList<>();
listWithRandomSize.forEach(data -> {
listToSend.add(data);
i++;
if (i%10 == 0) {
ListenableFuture<Void> futureResult = restTemplate.postForObject("http://receiver:8080/save/", listToSend);
allFutures.add(convertToCompletableFuture(futureResult));
listToSend = new ArrayList<>();
i = 0;
}
}
// sending is finished when reaching this point
CompletableFuture joinedFuture = CompletableFuture.allOf(allFutures.toArray(new CompletableFuture[allFutures.size()]));
joinedFuture.join();
//at this point save will have finished for all chunks
for (CompletableFuture future : allFutures) {
furture.get();
}