如何在不阻塞的情况下从单声道返回地图的值

问题描述 投票:0回答:0

我正在尝试实施反应性健康指标来检查多个目标服务的健康状况。

但是,相应的服务是 json 没有被解析。我知道 Mono of Health 有 Mono of Map。要删除 Map 的 Mono ,如果我使用 block() 那么它也会失败并出现错误,因为在反应式调用中不允许使用 block() 。我尝试使用 map() 函数并在另一个地图中填充值,但没有值被传递到该地图并且调用者没有订阅它。由于我使用的是 spring boot actuator,我不能强制调用者订阅,所以我怎样才能在健康检查中实现以下响应

期望的回应

> "reactiveTarget": {
>             "status": "UP"            {
>               "target1": {
>                   "status": "UP"
>               },
>               "target2": {
>                   "status": "UP"
>               }           }
>         },

达成的回应

"reactiveTarget": {
            "status": "UP",
            "details": {
                "target1": {
                    "scanAvailable": true
                },
                "holdingsWebClient": {
                    "target2": true
                }
            }
        },

使用的代码

@Component
@Slf4j
public class ReactiveTargetHealthIndicator implements ReactiveHealthIndicator {

    private final ApplicationContext context;

    private String overallStatus="UP";

    public ReactiveTargetHealthIndicator(@NonNull ApplicationContext context) {
        this.context = context;
    }

    @Override
    public Mono<Health> health() {
        return checkTargetServiceHealth().onErrorResume(
                ex -> Mono.just(new Health.Builder().down(ex).build())
        );
    }

    private Mono<Health> checkTargetServiceHealth() {
        var target = this.context;
        Map<String, Mono<Map<String, String>>> targetServiceBeans= new LinkedHashMap<>();
        while (target != null) {
            target.getBeansOfType(WebClient.class)
                    .forEach((name, webclient) -> targetServiceBeans.put(name, createReport(name,webclient)));
            target = target.getParent();
        }
        log.info("Reactive Webclient Beans [{}]", targetServiceBeans); // Bean is empty
        var heathBuilder = new Health.Builder().withDetails(targetServiceBeans);
        return (overallStatus.equals("DOWN") )? Mono.just(heathBuilder.down().build())
                : Mono.just(heathBuilder.up().build());
    }

    private Mono<Map<String, String>> createReport(String name, WebClient webclient) {
        log.info("Reactive Webclient [{}] is triggered", name); // Here name of bean is coming
        return webclient.get()
                .uri("/actuator/health/liveness")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Map<String, String>>() {
                })
                .onErrorResume(e -> {
                    log.error("Could not retrieve reactive health status of : {}", name, e);
                    overallStatus="DOWN";
                    return Mono.just(Map.of("status", "DOWN"));
                });
    }
}
java spring-boot spring-webflux reactive spring-boot-actuator
© www.soinside.com 2019 - 2024. All rights reserved.