[英]Spring Reactive in Microservices using rest calls
我使用 spring 引导 web 通量从事微服务项目,这里有一些服务:
我正在 OrderService 中实现一项服务,该服务将具有以下流程:
@PostMapping("/create")
//@PostMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Mono<OrderDto> createOrder(@RequestParam Publisher<OrderRequestDto> orderRequest){
return service.createOrder(Mono.from(orderRequest));
}
这是我的服务:
public Mono<OrderDto> createOrder(Mono<OrderRequestDto> orderRequest){
rule.validate(orderRequest); //returns Mono<OrderRequestDto>
//====== in the same time after validation =======//
//@todo call baseInfoService to get some data
//@todo call baseInfoService to get some other data
//@todo call performService and send orderRequest to get some data
//====== after getting above request do ======//
//@todo calculate and fill some order data acording above request results
//====== from here temporary I will use blocking style ======//
OrderEntity order = transformer.transform(orderRequest);
order = repository.save(order);
OrderDto orderDto = transformer.transformToDto(order);
//======== after above calculation and save do these operation in the same time =======//
//@todo call accountService and send orderDto to serive
//failure on this service is important and I should take proper action (there should be a call back instead of continue and sending notif)
//@todo call notificationService and send orderDto to service
return Mono.just(orderDto);
}
现在我应该使用 webClient 进行服务调用,将来我会使用 kafka 和 spring 云 stream 并将请求作为事件发送。
Publisher<OrderRequestDto>
还是OrderRequestDto
?谢谢你。
首先,如果您使用 reactor,则不应调用阻塞 API,就像您在 save 方法中所做的那样。 当您使用 webflux 时,您的线程数量很少,如果您阻塞这些线程,您的应用程序性能将会很差。 我建议改用反应式数据库驱动程序。
1、你不应该在controller中使用平面object,因为你必须阻塞线程才能得到object本身。 在reactor中,你不能调用阻塞操作。 如果您不确定什么是阻塞,还建议使用 blockhound。 如果调用阻塞方法,它将在测试期间抛出异常。
2,在反应式 stream 中,您必须使用反应式操作,例如map
, flatmap
等。对您的对象进行操作。
例如,假设你想通过一个对象列表来 go,从 web 中加载一些数据到每个对象中,然后将它们保存到数据库中(注意这里我将使用 mock db 和 webservice,但是你可以将它们更改为真正的服务而例子的本质是处理器。另外我这里用的是Kotlin,和Java类似)
//Mock repository
object ReactorDatabase {
fun saveData(car: Car): Mono<Car> = Mono.just(Car(1, car.producer,car.type))
fun loadData(): Flux<Vehicle> = Flux.just(Vehicle("Toyota"), Vehicle("Ford"))
}
//Mock webservice
object ReactiveWebService {
fun loadFromWeb(): Mono<String> = Mono.just("corolla").delayElement(Duration.ofMillis(100))
}
处理器 function:
//Load vehicles
//Map vehicles to cars
//Load car type somewhere from the web and zip with the car
//Add type to car
//Save cars into database
//Return with the saved entites
fun process(): Flux<Car>{
return ReactorDatabase.loadData()
.map { Mapper.vehicleToCar(it) }
.zipWith(ReactiveWebService.loadFromWeb())
.map { (car, type) -> Mapper.carWithDetails(car, type) }
.concatMap { ReactorDatabase.saveData(it) }
}
如您所见,所有方法都是从反应流中调用的。 当您使用反应式 IO 操作时,它总是返回一个发布者。 您可以使用flatMap
, concatMap
... 来获取 object 并在 stream 上无阻塞地推动。 此外,如果您的操作没有阻塞,那么您可以从map
调用 Mappers 等方法。
使用 reactor,您无法使用命令式编程风格(使用协程或类似的 struff 除外)。
这里还有一个反应 spring 云 stream 的示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.