简体   繁体   English

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

[英]Spring Reactive in Microservices using rest calls

I work on a micro-service project using spring boot web flux and here are some services:我使用 spring 引导 web 通量从事微服务项目,这里有一些服务:

  • baseInfoService基本信息服务
  • notificationService通知服务
  • accountService账户服务
  • orderService订单服务
  • performService执行服务

I'm implementing a service in OrderService which would has this flow:我正在 OrderService 中实现一项服务,该服务将具有以下流程:

@PostMapping("/create")
//@PostMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Mono<OrderDto> createOrder(@RequestParam Publisher<OrderRequestDto> orderRequest){
    return service.createOrder(Mono.from(orderRequest));
}

here is my service:这是我的服务:

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);
}

for now I should use webClient for services calls and in future I would use kafka and spring cloud stream and send requests as events.现在我应该使用 webClient 进行服务调用,将来我会使用 kafka 和 spring 云 stream 并将请求作为事件发送。

  • first question is should I use Publisher<OrderRequestDto> or OrderRequestDto in controller?第一个问题是我应该在 controller 中使用Publisher<OrderRequestDto>还是OrderRequestDto
  • second question: I have seen many simple samples existing in github and other sites but all just get a mono from repository and pass it to controller to return to user and I couldn't find a complicated real world example like this scenario.第二个问题:我在 github 和其他站点中看到了许多简单的示例,但都只是从存储库中获取 mono 并将其传递给 controller 以返回给用户的复杂示例,而我无法找到真实世界的示例。 could you please provide the way I should implement it.您能否提供我应该实施它的方式。

thank you.谢谢你。

First, if you use reactor you shouldnt call blocking apis, as you did it in the save method.首先,如果您使用 reactor,则不应调用阻塞 API,就像您在 save 方法中所做的那样。 When you use webflux, you have a small number of threads and if you block those threads your application performance will be very poor.当您使用 webflux 时,您的线程数量很少,如果您阻塞这些线程,您的应用程序性能将会很差。 I suggest using reactive database driver instead.我建议改用反应式数据库驱动程序。

1, You shouldnt use plane object in the controller, because you have to block the thread to get the object itself. 1、你不应该在controller中使用平面object,因为你必须阻塞线程才能得到object本身。 In reactor, you mustnt call blocking operation.在reactor中,你不能调用阻塞操作。 Also suggest to use blockhound if you are not sure about what is blocking.如果您不确定什么是阻塞,还建议使用 blockhound。 It will throw an exception during tests if blocking methods are called.如果调用阻塞方法,它将在测试期间抛出异常。

2, In reactive stream, you have to use the reactive operations, like map , flatmap , etc.. to do operations on your objects. 2,在反应式 stream 中,您必须使用反应式操作,例如mapflatmap等。对您的对象进行操作。

For example, suppose you want to go through a list of objects, load some data from web to each and save those into the database (note that here I'm going to use mock db and webservice, but you can change those into real services and the essence of the example is the processor. Also I use Kotlin here, which is similar to Java)例如,假设你想通过一个对象列表来 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))
}

The processor function:处理器 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) }
    }

As you can see, all methods were called from reactive streams.如您所见,所有方法都是从反应流中调用的。 When you use reactive IO operation, it always returns with a Publisher.当您使用反应式 IO 操作时,它总是返回一个发布者。 You can use flatMap , concatMap ... to get the object and push towards on the stream without blocking.您可以使用flatMapconcatMap ... 来获取 object 并在 stream 上无阻塞地推动。 Also if your operation does not block then you can call methods like Mappers from map .此外,如果您的操作没有阻塞,那么您可以从map调用 Mappers 等方法。

With reactor you are not able to use imperative programming style (except using coroutines or similar struffs).使用 reactor,您无法使用命令式编程风格(使用协程或类似的 struff 除外)。

Also here is an example to reactive spring cloud stream. 这里还有一个反应 spring 云 stream 的示例。

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

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