Spring 从返回未来的服务创建Mono/Flux的正确方法
我如何正确处理从未来构建的Monos 我正试着了解SpringResponsive(和Spring5),看所有的视频,阅读所有我能找到的博客,但他们似乎都停止了做一些事情,而不仅仅是查询数据库或其他琐碎的事情 我正在使用新的AWS 2.0 SDK,它在大多数情况下使用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
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);
}
}