GOOGLE ADS

Mittwoch, 13. April 2022

Wie man Mono#block() vermeidet, wenn man Reaktive in Rest-API-Logik verwendet

Das Problem ist also folgendes:

  • Ich stelle die API zur Verfügung, um Benutzer in meinem Dienst zu registrieren

  • Bevor ich einen Benutzer registriere, möchte ich ihn im externen Dienst (Rest-API) validieren.

  • Ich möchte den Benutzer mit dem richtigen Antwortstatus darüber informieren, ob er erstellt wurde (201 oder ein Fehlercode).

  • Mein Code zum Erstellen von Benutzern sieht so aus:

     @Transactional
    public void createUser(UserDto userDto) {
    UserEntity newUser = userFactory.createUser(userDto);
    String userId = userDto.getUserId();
    externalApiService
    .validateUser(userId)
    .subscribe(a-> userRepository.save(newUser));
    }

    und Validierung des Benutzers ist wie folgt:

     public Mono<Void> validateUser(String userId) {
    return webClient
    .get(...)
    .retrieve()
    .toEntity(Void.class);
    //Exact request is bit more complicated, but those details shouldn't be crucial in this example
    }

    Mein Endpunkt, der dies verwendet, sieht so aus:

     @PostMapping
    public ResponseEntity<Void> createUser(@Valid @RequestBody UserDto dto) {
    userService.createUser(dto);
    return new ResponseEntity<>(HttpStatus.CREATED);
    }

    Das ist ganz einfach, wenn ich das Blockieren RestTemplateverwende oder das benutze block(), Monowas ich gerade von bekommen habe WebClient. Wenn es eine Ausnahme vom REST-Aufruf an den externen Dienst gibt, erledigt mein globaler Ausnahmehandler die Aufgabe und antwortet dem Benutzer mit dem richtigen Antwortcode.

    Aber was ist, wenn ich die volle Kraft der reaktiven Programmierung nutzen möchte und nicht will block(). Ich kann nicht herausfinden, wie man das richtig macht. Kann mir jemand einen Rat geben?

    Und bitte entschuldigen Sie, wenn meine Frage trivial ist, ich bin ziemlich neu in der WebClientreaktiven Programmierung.


    Lösung des Problems

    WebClientist ein reaktiver Client und die einzige Möglichkeit, ihn mit nicht reaktivem Spring MVC zu verwenden, ist block.

    Um den Fluss vollständig blockierungsfrei zu machen, sollten alle Komponenten/Funktionen reaktiv sein. Sie müssten zu Spring WebFlux wechseln und auch createUserreaktiv machen.

    @PostMapping
    public Mono<ResponseEntity<Void>> createUser(@RequestBody UserDto dto) {
    return userService.createUser(dto)
    .map(user -> ResponseEntity.status(HttpStatus.CREATED).build());
    }

    Dieser Code geht davon aus, dass createUserer reaktiv ist

    public static Mono<UserEntity> createUser(UserDto dto) {
    ...
    }

    Falls userRepositoryes nicht reaktiv ist, können Sie nicht reaktiven Code umschließen und auf einem separaten Planer ausführen. Wie umschließe ich einen synchronen, blockierenden Anruf?.

    Keine Kommentare:

    Kommentar veröffentlichen

    Warum werden SCHED_FIFO-Threads derselben physischen CPU zugewiesen, obwohl CPUs im Leerlauf verfügbar sind?

    Lösung des Problems Wenn ich das richtig verstehe, versuchen Sie, SCHED_FIFO mit aktiviertem Hyperthreading ("HT") zu verwenden, ...