Java Reactor单执行并行任务
我不熟悉Reactor框架,并尝试在现有的实现中使用它。LocationProfileService和InventoryService都返回一个Mono,并并行执行,彼此之间没有依赖关系(来自MainService)。在LocationProfileService中-发出了4个查询,最后2个查询依赖于第一个查询 写这篇文章的更好方法是什么?我看到调用按顺序执行,而其中一些调用应该并行执行。正确的方法是什么Java Reactor单执行并行任务,java,reactive-programming,spring-webflux,project-reactor,reactor,Java,Reactive Programming,Spring Webflux,Project Reactor,Reactor,我不熟悉Reactor框架,并尝试在现有的实现中使用它。LocationProfileService和InventoryService都返回一个Mono,并并行执行,彼此之间没有依赖关系(来自MainService)。在LocationProfileService中-发出了4个查询,最后2个查询依赖于第一个查询 写这篇文章的更好方法是什么?我看到调用按顺序执行,而其中一些调用应该并行执行。正确的方法是什么 public class LocationProfileService {
public class LocationProfileService {
static final Cache<String, String> customerIdCache //define Cache
@Override
public Mono<LocationProfileInfo> getProfileInfoByLocationAndCustomer(String customerId, String location) {
//These 2 are not interdependent and can be executed immediately
Mono<String> customerAccountMono = getCustomerArNumber(customerId,location) LocationNumber).subscribeOn(Schedulers.parallel()).switchIfEmpty(Mono.error(new CustomerNotFoundException(location, customerId))).log();
Mono<LocationProfile> locationProfileMono = Mono.fromFuture(//location query).subscribeOn(Schedulers.parallel()).log();
//Should block be called, or is there a better way to do ?
String custAccount = customerAccountMono.block(); // This is needed to execute and the value from this is needed for the next 2 calls
Mono<Customer> customerMono = Mono.fromFuture(//query uses custAccount from earlier step).subscribeOn(Schedulers.parallel()).log();
Mono<Result<LocationPricing>> locationPricingMono = Mono.fromFuture(//query uses custAccount from earlier step).subscribeOn(Schedulers.parallel()).log();
return Mono.zip(locationProfileMono,customerMono,locationPricingMono).flatMap(tuple -> {
LocationProfileInfo locationProfileInfo = new LocationProfileInfo();
//populate values from tuple
return Mono.just(locationProfileInfo);
});
}
private Mono<String> getCustomerAccount(String conversationId, String customerId, String location) {
return CacheMono.lookup((Map)customerIdCache.asMap(),customerId).onCacheMissResume(Mono.fromFuture(//query).subscribeOn(Schedulers.parallel()).map(x -> x.getAccountNumber()));
}
}
public class InventoryService {
@Override
public Mono<InventoryInfo> getInventoryInfo(String inventoryId) {
Mono<Inventory> inventoryMono = Mono.fromFuture(//inventory query).subscribeOn(Schedulers.parallel()).log();
Mono<List<InventorySale>> isMono = Mono.fromFuture(//inventory sale query).subscribeOn(Schedulers.parallel()).log();
return Mono.zip(inventoryMono,isMono).flatMap(tuple -> {
InventoryInfo inventoryInfo = new InventoryInfo();
//populate value from tuple
return Mono.just(inventoryInfo);
});
}
}
public class MainService {
@Autowired
LocationProfileService locationProfileService;
@Autowired
InventoryService inventoryService
public void mainService(String customerId, String location, String inventoryId) {
Mono<LocationProfileInfo> locationProfileMono = locationProfileService.getProfileInfoByLocationAndCustomer(....);
Mono<InventoryInfo> inventoryMono = inventoryService.getInventoryInfo(....);
//is using block fine or is there a better way to do?
Mono.zip(locationProfileMono,inventoryMono).subscribeOn(Schedulers.parallel()).block();
}
}
公共类LocationProfileService{
静态最终缓存customerIdCache//定义缓存
@凌驾
公共Mono getProfileInfoByLocationAndCustomer(字符串customerId,字符串位置){
//这两项不是相互依赖的,可以立即执行
Mono customerAccountMono=getCustomerArNumber(customerId,location)LocationNumber).subscribeOn(Schedulers.parallel()).switchIfEmpty(Mono.error(new CustomerNotFoundException(location,customerId)).log();
Mono locationProfileMono=Mono.fromFuture(//位置查询).subscribeOn(Schedulers.parallel()).log();
//应该调用block,还是有更好的方法?
String custAccount=customerAccountMono.block();//执行时需要使用该值,接下来的2次调用需要使用该值中的值
Mono customerMono=Mono.fromFuture(//查询使用前面步骤中的custAccount);
Mono locationPricingMono=Mono.fromFuture(//查询使用前面步骤中的custAccount);
返回Mono.zip(locationProfileMono、customerMono、locationPricingMono).flatMap(元组->{
LocationProfileInfo LocationProfileInfo=新的LocationProfileInfo();
//从元组填充值
返回Mono.just(locationProfileInfo);
});
}
私有Mono getCustomerAccount(字符串会话ID、字符串customerId、字符串位置){
返回CacheMono.lookup((Map)customerIdCache.asMap(),customerId).onCacheMissResume(Mono.fromFuture(//query).subscribeOn(Schedulers.parallel()).Map(x->x.getAccountNumber());
}
}
公共类目录服务{
@凌驾
public Mono getInventoryInfo(字符串inventoryId){
Mono inventoryMono=Mono.fromFuture(//库存查询).subscribeOn(Schedulers.parallel()).log();
Mono isMono=Mono.fromFuture(//库存销售查询).subscribeOn(Schedulers.parallel()).log();
返回Mono.zip(inventoryMono,isMono).flatMap(元组->{
InventoryInfo InventoryInfo=新的InventoryInfo();
//从元组填充值
返回Mono.just(inventoryInfo);
});
}
}
公共类主服务{
@自动连线
LocationProfileService LocationProfileService;
@自动连线
库存服务库存服务
公共void mainService(字符串customerId、字符串位置、字符串inventoryId){
Mono locationProfileMono=locationProfileService.getProfileInfoByLocationAndCustomer(..);
Mono inventoryMono=inventoryService.getInventoryInfo(..);
//使用block是好的还是有更好的方法?
zip(locationProfileMono,inventoryMono).subscribeOn(Schedulers.parallel()).block();
}
}
您无需阻塞即可获得pass参数,因为您的代码非常接近解决方案。我使用您提供的类名编写了代码。只需将所有Mono.Just(..)替换为对正确服务的调用
public Mono<LocationProfileInfo> getProfileInfoByLocationAndCustomer(String customerId, String location) {
Mono<String> customerAccountMono = Mono.just("customerAccount");
Mono<LocationProfile> locationProfileMono = Mono.just(new LocationProfile());
return Mono.zip(customerAccountMono, locationProfileMono)
.flatMap(tuple -> {
Mono<Customer> customerMono = Mono.just(new Customer(tuple.getT1()));
Mono<Result<LocationPricing>> result = Mono.just(new Result<LocationPricing>());
Mono<LocationProfile> locationProfile = Mono.just(tuple.getT2());
return Mono.zip(customerMono, result, locationProfile);
})
.map(LocationProfileInfo::new)
;
}
public static class LocationProfileInfo {
public LocationProfileInfo(Tuple3<Customer, Result<LocationPricing>, LocationProfile> tuple){
//do wathever
}
}
public static class LocationProfile {}
private static class Customer {
public Customer(String cutomerAccount) {
}
}
private static class Result<T> {}
private static class LocationPricing {}
公共Mono getProfileInfoByLocationAndCustomer(字符串customerId,字符串位置){
Mono customerAccountMono=Mono.just(“customerAccount”);
Mono locationProfileMono=Mono.just(new LocationProfile());
return Mono.zip(customerAccountMono,locationProfileMono)
.flatMap(元组->{
Mono customerMono=Mono.just(新客户(tuple.getT1());
Mono result=Mono.just(new result());
Mono locationProfile=Mono.just(tuple.getT2());
返回Mono.zip(customerMono、result、locationProfile);
})
.map(LocationProfileInfo::新建)
;
}
公共静态类LocationProfileInfo{
公共位置配置文件信息(Tuple3 tuple){
//杜瓦瑟弗
}
}
公共静态类LocationProfile{}
私有静态类客户{
公共客户(字符串客户帐户){
}
}
私有静态类结果{}
私有静态类LocationPricing{}
请记住,第一个拉链不是必需的。我重写它是为了得到你的解决方案。但我会用不同的方式来解决这个问题。这会更清楚
public Mono<LocationProfileInfo> getProfileInfoByLocationAndCustomer(String customerId, String location) {
return Mono.just("customerAccount") //call the service
.flatMap(customerAccount -> {
//declare the call to get the customer
Mono<Customer> customerMono = Mono.just(new Customer(customerAccount));
//declare the call to get the location pricing
Mono<Result<LocationPricing>> result = Mono.just(new Result<LocationPricing>());
//declare the call to get the location profile
Mono<LocationProfile> locationProfileMono = Mono.just(new LocationProfile());
//in the zip call all the services actually are executed
return Mono.zip(customerMono, result, locationProfileMono);
})
.map(LocationProfileInfo::new)
;
公共Mono getProfileInfoByLocationAndCustomer(字符串customerId,字符串位置){
返回Mono.just(“customerAccount”)//调用服务
.flatMap(customerAccount->{
//声明呼叫以获取客户
Mono customerMono=Mono.just(新客户(customerAccount));
//声明调用以获取位置定价
Mono result=Mono.just(new result());
//声明调用以获取位置配置文件
Mono locationProfileMono=Mono.just(new LocationProfile());
//在zip调用中,所有服务实际上都被执行
返回Mono.zip(customerMono、result、locationProfileMono);
})