繁体   English   中英

Spring 使用 rest 调用的微服务中的响应式

[英]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 并将请求作为事件发送。

  • 第一个问题是我应该在 controller 中使用Publisher<OrderRequestDto>还是OrderRequestDto
  • 第二个问题:我在 github 和其他站点中看到了许多简单的示例,但都只是从存储库中获取 mono 并将其传递给 controller 以返回给用户的复杂示例,而我无法找到真实世界的示例。 您能否提供我应该实施它的方式。

谢谢你。

首先,如果您使用 reactor,则不应调用阻塞 API,就像您在 save 方法中所做的那样。 当您使用 webflux 时,您的线程数量很少,如果您阻塞这些线程,您的应用程序性能将会很差。 我建议改用反应式数据库驱动程序。

1、你不应该在controller中使用平面object,因为你必须阻塞线程才能得到object本身。 在reactor中,你不能调用阻塞操作。 如果您不确定什么是阻塞,还建议使用 blockhound。 如果调用阻塞方法,它将在测试期间抛出异常。

2,在反应式 stream 中,您必须使用反应式操作,例如mapflatmap等。对您的对象进行操作。

例如,假设你想通过一个对象列表来 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 操作时,它总是返回一个发布者。 您可以使用flatMapconcatMap ... 来获取 object 并在 stream 上无阻塞地推动。 此外,如果您的操作没有阻塞,那么您可以从map调用 Mappers 等方法。

使用 reactor,您无法使用命令式编程风格(使用协程或类似的 struff 除外)。

这里还有一个反应 spring 云 stream 的示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM