Spring 从返回未来的服务创建Mono/Flux的正确方法

Spring 从返回未来的服务创建Mono/Flux的正确方法,spring,spring-boot,mono,completable-future,spring-webflux,Spring,Spring Boot,Mono,Completable Future,Spring Webflux,我如何正确处理从未来构建的Monos 我正试着了解SpringResponsive(和Spring5),看所有的视频,阅读所有我能找到的博客,但他们似乎都停止了做一些事情,而不仅仅是查询数据库或其他琐碎的事情 我正在使用新的AWS 2.0 SDK,它在大多数情况下使用CompletableFuture。使用服务创建一个新实例,我的方法如下 public Mono<RunInstancesResponse> create(Instance instance) { RunInst

我如何正确处理从未来构建的Monos

我正试着了解SpringResponsive(和Spring5),看所有的视频,阅读所有我能找到的博客,但他们似乎都停止了做一些事情,而不仅仅是查询数据库或其他琐碎的事情

我正在使用新的AWS 2.0 SDK,它在大多数情况下使用
CompletableFuture
。使用服务创建一个新实例,我的方法如下

public Mono<RunInstancesResponse> create(Instance instance) {
    RunInstancesRequest runInstancesRequest = RunInstancesRequest.builder()
            .instanceType(instance.getInstanceType())
            .imageId(instance.getImageId())
            .securityGroupIds(instance.getSecurityGroupIds())
            .keyName(instance.getKeyName())
            .minCount(1)
            .maxCount(1)
            .tagSpecifications(createTags(instance))
            .build();

    CompletableFuture<RunInstancesResponse> future = client.runInstances(runInstancesRequest);

    future.whenComplete((response, error) -> {
        response.reservation().instances().stream().map(aws -> Instance.builder()
                .imageId(aws.imageId())
                .build()
        ).forEach(instanceRepository::save);

    });

    return Mono.fromFuture(future);
}
现在,这几乎像我预期的那样起作用,但是有几个关键问题我不知道如何解决

1.
whenComplete
从未被调用,我相信这是因为我没有订阅它

2.)服务器在完成
whenComplete
之前不会响应客户端(大约2.5秒),这并不理想,因为我希望它立即响应,然后在调用
whenComplete
时更新客户端

我觉得我的整个服务和处理方式完全是错误的

我想举一些例子,说明我应该如何在一个服务中处理未来,在这个服务中,它是从一个带有
Mono
Flux
类型的路由处理程序调用的。

我写了一个包括SQS、SNS和DynamoDb的示例,使这更容易一些。要避免仅链接答案,您可以对其应用以下内容:

public Mono<ChangeMessageVisibilityResult> changeMessageVisibility(String queueUrl, String receiptHandle, Integer visibilityTimeout) {
    return Mono.create(subscriber -> amazonClient.changeMessageVisibilityAsync(queueUrl, receiptHandle, visibilityTimeout, AmazonWebServiceRequestAsyncHandler.valueEmittingHandlerFor(subscriber)));
  }
公共Mono changeMessageVisibility(字符串queueUrl、字符串receiptHandle、整数visibilityTimeout){ 返回Mono.create(subscriber->amazonClient.changeMessageVisibilityAsync(queueUrl、receiptHandle、visibilityTimeout、AmazonWebServiceRequestStatAsynchHandler.valueEmittingHandlerFor(subscriber)); } 传递的处理程序在两个世界之间转换:

public class AmazonWebServiceRequestAsyncHandler<RQ extends AmazonWebServiceRequest, RS> implements AsyncHandler<RQ, RS> {
    private final MonoSink<? super RS> subscriber;
    private boolean shouldEmitValue;

    private AmazonWebServiceRequestAsyncHandler(MonoSink<? super RS> subscriber, boolean shouldEmitValue) {
        this.subscriber = subscriber;
        this.shouldEmitValue = shouldEmitValue;
    }

    @Override
    public void onError(Exception exception) {
        subscriber.error(exception);
    }

    @Override
    public void onSuccess(RQ request, RS response) {
        if (shouldEmitValue) {
            subscriber.success(response);
        } else {
            subscriber.success();
        }
    }

    public static <RQ extends AmazonWebServiceRequest, RS> AsyncHandler<RQ, RS> valueEmittingHandlerFor(final MonoSink<? super RS> subscriber) {
        return new AmazonWebServiceRequestAsyncHandler<>(subscriber, true);
    }

    public static <RQ extends AmazonWebServiceRequest> AsyncHandler<RQ, Void> voidHandlerFor(MonoSink<? super Void> subscriber) {
        return new AmazonWebServiceRequestAsyncHandler<>(subscriber, false);
    }
}
公共类AmazonWebServiceRequestStatAsyncHandler实现AsyncHandler{

私有的最后一点1.和2.似乎是矛盾的,因为您说永远不会调用
whenComplete()
,并且只有在执行
whenComplete()
之后才会得到响应。您调用
whenComplete()的方式
不过对我来说似乎不错,但问题可能在于线程池的大小不允许您所需的并发性?您看过Mono.fromFuture(future)吗?
public class AmazonWebServiceRequestAsyncHandler<RQ extends AmazonWebServiceRequest, RS> implements AsyncHandler<RQ, RS> {
    private final MonoSink<? super RS> subscriber;
    private boolean shouldEmitValue;

    private AmazonWebServiceRequestAsyncHandler(MonoSink<? super RS> subscriber, boolean shouldEmitValue) {
        this.subscriber = subscriber;
        this.shouldEmitValue = shouldEmitValue;
    }

    @Override
    public void onError(Exception exception) {
        subscriber.error(exception);
    }

    @Override
    public void onSuccess(RQ request, RS response) {
        if (shouldEmitValue) {
            subscriber.success(response);
        } else {
            subscriber.success();
        }
    }

    public static <RQ extends AmazonWebServiceRequest, RS> AsyncHandler<RQ, RS> valueEmittingHandlerFor(final MonoSink<? super RS> subscriber) {
        return new AmazonWebServiceRequestAsyncHandler<>(subscriber, true);
    }

    public static <RQ extends AmazonWebServiceRequest> AsyncHandler<RQ, Void> voidHandlerFor(MonoSink<? super Void> subscriber) {
        return new AmazonWebServiceRequestAsyncHandler<>(subscriber, false);
    }
}