当前位置: 首页 > 知识库问答 >
问题:

使用rest调用的微服务中的Spring Reactive

郭思聪
2023-03-14

我使用spring boot web flux从事一个微服务项目,下面是一些服务:

  • BaseInfoService
  • 通知服务
  • 会计服务
  • 订单服务
  • PerformService
@PostMapping("/create")
//@PostMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Mono<OrderDto> createOrder(@RequestParam OrderRequestDto orderRequest){
    return service.createOrder(orderRequest);
}
public Mono<OrderDto> createOrder(OrderRequestDto orderRequest){
    rule.validate(orderRequest);

    //====== in the same time =======//

    //@todo call baseInfoService to get some data

    //@todo call baseInfoService to get some other data

    //@todo call performService to send orderRequest some calculation

    //====== after getting above request ======//

    //@todo calculate and fill some order data acording above request results        

    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 to effect the accounts
    //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 to inform related users

    return Mono.just(orderDto);
}

现在,我应该使用webClient进行服务调用,将来我会使用kafka和spring cloud stream并将请求作为事件发送。

  • 第一个问题是我应该在控制器中使用发布服务器 还是orderrequestdto
  • 第二个问题:我在github和其他站点中看到了许多简单的示例,但所有这些示例都只是从存储库中获取一个mono,然后将其传递给controller以返回给用户,而我找不到像这样复杂的现实世界示例。你能提供我应该如何实施它吗?

谢谢你。

共有1个答案

伯俊弼
2023-03-14

首先,如果使用ractor,就不应该像在save方法中那样调用阻塞API。当您使用webflux时,您只有少量的线程,如果您阻止这些线程,您的应用程序性能将非常差。我建议改用反应型数据库驱动程序。

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

2、在reactive流中,必须使用reactive操作,如mapflatmap等。对对象执行操作。

例如,假设您想查看一个对象列表,将一些数据从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))
}

处理器功能:

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

正如您所看到的,所有方法都是从反应流调用的。当您使用reactive IO操作时,它总是返回一个发布服务器。您可以使用flatmapconcatmap...获取对象并在不阻塞的情况下将其推向流。此外,如果您的操作没有阻塞,那么您可以从map中调用类似映射器的方法。

对于reactor,您不能使用命令式编程风格(除了使用协式或类似的struffs)。

这里还有一个反应性的Spring云流的例子。

 类似资料:
  • 对于一个项目,我想使用Spring Boot设置一个小型微服务场景,其中有一个向客户端公开REST和GraphQL的API网关、一个Eureka服务注册表和三个服务。由于性能原因,我希望API网关后面的所有服务都可以谈论gRPC,但同时仍然会公开一个额外的REST API。有没有一种干净的方法可以在相同的业务逻辑上实现这两种类型的接口?网关如何将客户端的HTTP请求代理到gRPC请求?

  • 在我们的项目中,我们使用Spring cloud Eureka作为服务注册中心。当我们使用ribbon客户端调用内部微服务时,所有URL都通过Eureka解析。。。调用外部URL是个问题。由于外部API是老式的,所以使用Feign似乎不是一个好选择。 从这样的服务调用外部URL的最佳方式是什么? 提前谢谢 帕特里斯

  • 我有一个springbootmicroservice,它包含一个我需要在每个星期天运行的方法,所以我在方法上使用@Scheduled注释,在配置类中使用@EnableScheduling注释。用@Scheduling注释的方法调用另一个方法,该方法反过来调用一个客户端类,在该类中,通过对另一个微服务进行rest调用获取响应,但rest调用步骤未执行,并且当我从控制器触发该方法时,当我使用计划注释时

  • 如果类路径上有SpringWebFlux,还可以选择使用WebClient调用远程REST服务。与RestTemplate相比,这个客户端具有更多的功能感和完全的反应性。您可以在SpringFrameworkdocs中的专用部分中了解更多关于WebClient的信息。 Spring Boot为您创建并预配置WebClient.Builder; 强烈建议将其注入组件并使用它来创建WebClient实

  • 如果需要从应用程序调用远程REST服务,可以使用Spring Framework的RestTemplate类。 由于RestTemplate实例在使用之前通常需要进行自定义,因此Spring Boot不提供任何单个自动配置的RestTemplate bean。 但是,它会自动配置RestTemplateBuilder,可用于在需要时创建RestTemplate实例。 自动配置的RestTempla

  • 我正在寻找一个最佳实践和高效的解决方案,以确保通过REST与Web客户端应用程序通信的多个微服务的安全。 当前设置: 这些微服务是用Java制作的,带有Spring框架,并运行在Docker容器中。 客户端是一个Angular 2应用程序。 我创建了一个新的µ服务,它将充当“网关”,是我的web客户端和其他服务之间的唯一通信点。 我从远程身份验证API检索JWT加密令牌(让我们称之为LOCK) 我