轮询弹簧启动执行器端点的更好方法(流式传输而不是轮询?)

Posted

技术标签:

【中文标题】轮询弹簧启动执行器端点的更好方法(流式传输而不是轮询?)【英文标题】:Better way to poll spring boot actuator endpoint (stream it instead of polling?) 【发布时间】:2020-03-22 13:42:45 【问题描述】:

我正在编写一个 Web UI 来监控 Spring Boot 中的另一个 Java 应用程序,由 Spring Actuator 支持。

现在我可以使用常规 Get 请求(通过 Spring WebFlux 的 WebClient.get() 方法)从其他客户端 Sprint Boot Web 应用程序轮询 Spring Actuator 的端点。

但是,如果某些数据发生变化,比如说指标端点之一(即 CPU 使用率总是在变化),我必须“刷新”get 请求。我可以通过@Scheduled 注解将它设置在预定的计时器上,但我觉得有更好的方法吗?

我知道如何从不断流动的数据的 get 请求中检索 Flux,但是在服务器上,必须创建一个 Flux。 Spring Boot Actuator 可以提供一个 Flux 的指标,以便我可以流式传输它吗?

这里有一些代码,我目前通过每 500 毫秒 ping 一次的预定方法调用此方法。

private Flux<Health> getHealth(String baseUrl) 

    var fallbackValue = new Health();
    fallbackValue.setStatus("Unknown");
    return webClient.get().uri(baseUrl + "/actuator/health").retrieve().bodyToFlux(Health.class)
            .onErrorReturn(fallbackValue);


但只有当我调用它并使用预定的注释总是刷新它时它才会更新:

@Scheduled(fixedDelay = 500) // I want to remove this, instead of refreshing, I want the data to stream
public void pollCapHandlers() 

    getHealth("http://localhost:8080").subscribe(health -> 
        ui.access(() -> 
            healthStatusTextField.setValue(health.getStatus()); // this doesn't update in real time
        );
    )

【问题讨论】:

【参考方案1】:

首先,您应该避免过于频繁地调用执行器端点,尤其是当您的应用程序不使用数据时。如果您的应用程序是仪表板,则除非有人当前正在查看该仪表板,否则它不应该获取数据。这排除了@Scheduled 的使用,无论如何都会发生这种情况。此外,执行器数据可以被缓存,或者可以在应用程序上创建一些负载,具体取决于端点。这应该慎重考虑。

现在您可以在投票应用程序中以这样的流方式实现这一点:


@GetMapping(path = "/status/application", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Status> streamStatus() 
  return Flux.interval(interval).flatMap(i -> getHealth(...));


这允许您定期轮询远程端点并将结果流式传输到浏览器(使用 SSE),而不会给远程应用程序增加不必要的负载。

【讨论】:

谢谢,我会试试这个。我绝对不想使用@scheduled,我把它作为一个临时的“hack”放在那里,直到我能以正确的方式做到这一点! :D

以上是关于轮询弹簧启动执行器端点的更好方法(流式传输而不是轮询?)的主要内容,如果未能解决你的问题,请参考以下文章

如何轮询 CoreLocation 而不是获取更新?

将控制台应用程序的标准输出流式传输到 ASP.NET MVC 视图

弹簧引导执行器端点未通过HTTP公开

apache骆驼轮询休息端点

Spring Integration 没有为端点定义轮询器

Java 和 Spring - 轮询 http 端点,直到服务器完成处理