了解异步接收数据是用Java完成的

时间:2017-09-11 11:26:11

标签: java spring data-synchronization asynchronous

我在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);  
    }
}

1 个答案:

答案 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();
}