1. 概述
本教程將教你如何配置 Spring Boot 3 的可觀測性。 可觀測性是指僅通過其外部輸出(日誌、指標和跟蹤)來衡量系統內部狀態的能力。 你可以在“分佈式系統中的可觀測性”中瞭解基本概念。
此外,我們必須意識到 Spring Boot 2 (Spring 5) 和 Spring Boot 3 (Spring 6) 之間存在顯著差異。 Spring 6 引入了 Spring 可觀測性,這是一個建立在 Micrometer 和 Micrometer Tracing (以前稱為 Spring Cloud Sleuth) 之上的新舉措。 它主要用於使用 Micrometer 記錄應用程序指標以及通過提供者(如 OpenZipkin 的 Brave 或 OpenTelemetry)實現跟蹤。 Spring 可觀測性優於基於代理的可觀測性解決方案, 因為它可以在原生編譯的 Spring 應用程序中無縫工作,並提供更全面的信息。
在這裏,我們將只關注 Spring Boot 3 的細節。 如果你想從 Spring Boot 2 遷移,可以在 這裏找到詳細説明。
2. Micrometer 觀察 API
Micrometer 是一個提供 vendor-中立的應用程序指標面版的項目。它定義了 諸如儀表、速率聚合、計數器、表計和定時器等概念,每個供應商都可以根據自己的概念和工具進行調整。其中一個核心部分是 觀察 API,它允許一次性地對代碼進行指標化,並具有多項優勢。
它作為 Spring Framework 的多個部分中的依賴項包含在內,因此我們需要了解這個 API 才能理解 Spring Boot 中觀察是如何工作的。我們可以通過一個簡單的示例來完成。
2.1. 觀察 和 ObservationRegistry
根據 dictionary.com 的定義,“觀察”是指“對事實或事件進行觀察或記錄,通常用於科學或其他特殊目的的行為或實例”。 在我們的代碼中,我們可以觀察單個操作或完整的 HTTP 請求處理。 在這些觀察過程中,我們可以進行測量、創建用於分佈式追蹤的 span,或者僅僅記錄其他信息。
為了創建觀察,我們需要一個 ObservationRegistry:
ObservationRegistry observationRegistry = ObservationRegistry.create();
Observation observation = Observation.createNotStarted("sample", observationRegistry);觀察具有如下生命週期,如圖所示:
我們可以使用 觀察 類型,例如:
observation.start();
try (Observation.Scope scope = observation.openScope()) {
// ... the observed action
} catch (Exception e) {
observation.error(e);
// further exception handling
} finally {
observation.stop();
}或者簡單地説:
observation.observe(() -> {
// ... the observed action
});2.2. ObservationHandler
數據收集代碼被實現為一個 ObservationHandler。該處理器會收到 Observation 生命週期事件的通知,因此提供回調方法。 這樣實現一個簡單的處理器,只需打印出事件即可:
public class SimpleLoggingHandler implements ObservationHandler<Observation.Context> {
private static final Logger log = LoggerFactory.getLogger(SimpleLoggingHandler.class);
@Override
public boolean supportsContext(Observation.Context context) {
return true;
}
@Override
public void onStart(Observation.Context context) {
log.info("Starting");
}
@Override
public void onScopeOpened(Observation.Context context) {
log.info("Scope opened");
}
@Override
public void onScopeClosed(Observation.Context context) {
log.info("Scope closed");
}
@Override
public void onStop(Observation.Context context) {
log.info("Stopping");
}
@Override
public void onError(Observation.Context context) {
log.info("Error");
}
}我們隨後在 ObservationRegistry 中註冊 ObservationHandler,然後再創建 Observation。
observationRegistry
.observationConfig()
.observationHandler(new SimpleLoggingHandler());對於簡單的日誌記錄,已經存在一個實現方案。例如,為了簡單地將事件記錄到控制枱,我們可以使用:
observationRegistry
.observationConfig()
.observationHandler(new ObservationTextPublisher(System.out::println));為了使用定時器樣本和計數器,我們可以配置如下:
MeterRegistry meterRegistry = new SimpleMeterRegistry();
observationRegistry
.observationConfig()
.observationHandler(new DefaultMeterObservationHandler(meterRegistry));
// ... observe using Observation with name "sample"
// fetch maximum duration of the named observation
Optional<Double> maximumDuration = meterRegistry.getMeters().stream()
.filter(m -> "sample".equals(m.getId().getName()))
.flatMap(m -> StreamSupport.stream(m.measure().spliterator(), false))
.filter(ms -> ms.getStatistic() == Statistic.MAX)
.findFirst()
.map(Measurement::getValue);
3. Spring Integration
Spring Integration 是一個基於 Spring 框架的集成解決方案,它允許你構建基於消息和事件的應用程序。它提供了豐富的集成能力,包括:
- 消息代理: 支持各種消息代理,如 RabbitMQ、Kafka、JMS 等。
- 通道和適配器: 通過通道和適配器,將不同的系統和應用程序連接起來。
- 流程定義: 使用 XML 或 DSL (Domain Specific Language) 定義複雜的集成流程。
- 事件處理: 支持事件驅動的架構,允許應用程序響應外部事件。
Spring Integration 旨在簡化企業應用集成,提高開發效率和可維護性。
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
// 這是一個簡單的 Spring Integration 示例
recepção
3.1. Actuator
我們通過引入 Actuator 依賴,在 Spring Boot 應用中獲得最佳集成:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>它包含一個 ObservationAutoConfiguration,它提供了一個可注入的 ObservationRegistry 實例(如果它尚不存在),並配置了 ObservationHandlers 用於收集指標和跟蹤。
例如,我們可以使用註冊表在服務中創建一個自定義的觀察結果:
@Service
public class GreetingService {
private ObservationRegistry observationRegistry;
// constructor
public String sayHello() {
return Observation
.createNotStarted("greetingService", observationRegistry)
.observe(this::sayHelloNoObserver);
}
private String sayHelloNoObserver() {
return "Hello World!";
}
}此外,它還向 ObservationRegistry 註冊了 ObservationHandler Bean。我們只需要提供這些 Bean:
@Configuration
public class ObservationTextPublisherConfiguration {
private static final Logger log = LoggerFactory.getLogger(ObservationTextPublisherConfiguration.class);
@Bean
public ObservationHandler<Observation.Context> observationTextPublisher() {
return new ObservationTextPublisher(log::info);
}
}3.2. Web
對於 MVC,有一個過濾器 (org.springframework.web.filter.ServerHttpObservationFilter) 可以用於 HTTP 服務器觀察。當 Actuator 包含在我們的應用程序中時,此過濾器已註冊並處於活動狀態。如果未包含,則需要配置它:
@Configuration
public class ObservationFilterConfiguration {
// if an ObservationRegistry is configured
@ConditionalOnBean(ObservationRegistry.class)
// if we do not use Actuator
@ConditionalOnMissingBean(ServerHttpObservationFilter.class)
@Bean
public ServerHttpObservationFilter observationFilter(ObservationRegistry registry) {
return new ServerHttpObservationFilter(registry);
}
}對於 WebFlux,存在一個過濾器 (org.springframework.web.filter.reactive.ServerHttpObservationFilter),但自 Spring Framework 6.1 (Spring Boot 3.2) 版本起,它已被棄用 (https://github.com/spring-projects/spring-framework/issues/31205)。相反,創建了一個 WebHttpHandlerBuilder。與 Actuator 配合使用時,這也被自動配置 (https://docs.spring.io/spring-boot/reference/web/reactive.html)。
3.3. AOP
Micrometer 觀察 API 還聲明瞭一個 @Observed 註解,其實現基於 AspectJ 的方面模型。為了使此功能正常工作,我們需要將 AOP 依賴項添加到我們的項目中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>然後,我們將該方面實現註冊為 Spring 管理的 Bean:
@Configuration
public class ObservedAspectConfiguration {
@Bean
public ObservedAspect observedAspect(ObservationRegistry observationRegistry) {
return new ObservedAspect(observationRegistry);
}
}現在,與其在我們的代碼中創建 Observation,不如我們儘快編寫 GreetingService:
@Observed(name = "greetingService")
@Service
public class GreetingService {
public String sayHello() {
return "Hello World!";
}
}
與 Actuator 結合使用時,我們可以通過 http://localhost:8080/actuator/metrics/greetingService 讀取預配置的指標(在至少調用一次服務後),並得到類似如下結果:
{
"name": "greetingService",
"baseUnit": "seconds",
"measurements": [
{
"statistic": "COUNT",
"value": 15
},
{
"statistic": "TOTAL_TIME",
"value": 0.0237577
},
{
"statistic": "MAX",
"value": 0.0035475
}
],
...
}4. 測試觀察
Micrometer 可觀測性 API 提供了一個模塊,允許我們編寫測試。 要做到這一點,我們需要添加這個依賴項:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-observation-test</artifactId>
<scope>test</scope>
</dependency>micrometer-bom 是 Spring Boot 管理依賴的一部分,因此我們無需指定任何版本。
由於默認情況下,整個可觀測性自動配置在測試中使用時被禁用,因此當我們想要測試默認的可觀測性時,需要使用 重新啓用它。
4.1. TestObservationRegistry</h3
我們可以使用 TestObservationRegistry,它允許使用 AssertJ 類型的斷言。因此,我們需要用 TestObservationRegistry 實例替換現有的 ObservationRegistry。
例如,如果我們想要測試 GreetingService 的觀察結果,可以使用以下測試設置:
@ExtendWith(SpringExtension.class)
@ComponentScan(basePackageClasses = GreetingService.class)
@EnableAutoConfiguration
@Import(ObservedAspectConfiguration.class)
@AutoConfigureObservability
class GreetingServiceObservationIntegrationTest {
@Autowired
GreetingService service;
@Autowired
TestObservationRegistry registry;
@TestConfiguration
static class ObservationTestConfiguration {
@Bean
TestObservationRegistry observationRegistry() {
return TestObservationRegistry.create();
}
}
// ...
}我們還可以使用 JUnit 元註解進行配置:
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import({
ObservedAspectConfiguration.class,
EnableTestObservation.ObservationTestConfiguration.class
})
@AutoConfigureObservability
public @interface EnableTestObservation {
@TestConfiguration
class ObservationTestConfiguration {
@Bean
TestObservationRegistry observationRegistry() {
return TestObservationRegistry.create();
}
}
}接下來,我們需要為我們的測試類添加註釋:
@ExtendWith(SpringExtension.class)
@ComponentScan(basePackageClasses = GreetingService.class)
@EnableAutoConfiguration
@EnableTestObservation
class GreetingServiceObservationIntegrationTest {
@Autowired
GreetingService service;
@Autowired
TestObservationRegistry registry;
// ...
}然後我們可以調用該服務,並檢查觀測是否已完成:
import static io.micrometer.observation.tck.TestObservationRegistryAssert.assertThat;
// ...
@Test
void testObservation() {
// invoke service
service.sayHello();
assertThat(registry)
.hasObservationWithNameEqualTo("greetingService")
.that()
.hasBeenStarted()
.hasBeenStopped();
}4.2. 觀察者處理程序兼容性套件
為了測試我們的 ObservationHandler 實現,我們可以從測試中繼承的幾個基礎類(稱為 兼容性套件):
- NullContextObservationHandlerCompatibilityKit 測試在處理 null 值參數時,觀察者處理程序是否正常工作。
- AnyContextObservationHandlerCompatibilityKit 測試在處理未指定測試上下文參數時,觀察者處理程序是否正常工作。 這也包括 NullContextObservationHandlerCompatibilityKit。
- ConcreteContextObservationHandlerCompatibilityKit 測試在處理上下文類型的測試上下文時,觀察者處理程序是否正常工作。
實現很簡單:
public class SimpleLoggingHandlerUnitTest
extends AnyContextObservationHandlerCompatibilityKit {
SimpleLoggingHandler handler = new SimpleLoggingHandler();
@Override
public ObservationHandler<Observation.Context> handler() {
return handler;
}
}
這將導致以下輸出:
5. Micrometer 追蹤
前 Spring Cloud Sleuth 項目已遷移到 Micrometer,Micrometer 追蹤的核心自 Spring Boot 3 起就使用了它。 您可以在以下 文檔 中找到 Micrometer 追蹤的定義:
Micrometer 追蹤提供了一個簡單的面向對象接口,用於最流行的追蹤庫,讓您可以在不鎖定供應商的情況下,對 JVM 應用程序代碼進行儀器化。 它旨在在不增加追蹤活動開銷的情況下,最大限度地提高追蹤工作的可移植性。
我們可以獨立使用它,但它也與 Observation API 集成,通過提供 ObservationHandler 擴展。
5.1. 集成到觀察 API
為了使用 Micrometer Tracing,我們需要將以下依賴項添加到我們的項目中。版本由 Spring Boot 管理:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing</artifactId>
</dependency>接下來,我們需要一個受支持的追蹤器(目前是 受支持的追蹤器,例如 OpenZipkin Brave 或 OpenTelemetry)。然後,我們需要為特定供應商的集成添加 Micrometer Tracing 的依賴項:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>或
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>Spring Actuator 具有對追蹤器的自動配置,即它會註冊供應商特定的對象和 Micrometer 追蹤的 ObservationHandler 實現,並將這些對象委託到應用程序上下文中。因此,無需進行任何進一步的配置步驟。
5.2. 測試支持
為了進行測試,我們需要將以下依賴項添加到我們的項目中。版本由 Spring Boot 管理:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-test</artifactId>
<scope>test</scope>
</dependency>然後我們可以使用 SimpleTracer 類在測試期間收集和驗證跟蹤數據。為了使其正常工作,我們將應用程序上下文中的原始、特定於供應商的 Tracer 替換為 SimpleTracer。 此外,我們還需要啓用跟蹤的自動配置,使用 @AutoConfigureObservability。
因此,跟蹤的最小測試配置可能如下所示:
@ExtendWith(SpringExtension.class)
@EnableAutoConfiguration
@AutoConfigureObservability
public class GreetingServiceTracingIntegrationTest {
@TestConfiguration
static class ObservationTestConfiguration {
@Bean
TestObservationRegistry observationRegistry() {
return TestObservationRegistry.create();
}
@Bean
SimpleTracer simpleTracer() {
return new SimpleTracer();
}
}
@Test
void shouldTrace() {
// test
}
}或者,如果我們使用 JUnit 元註解:
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@AutoConfigureObservability
@Import({
ObservedAspectConfiguration.class,
EnableTestObservation.ObservationTestConfiguration.class
})
public @interface EnableTestObservation {
@TestConfiguration
class ObservationTestConfiguration {
@Bean
TestObservationRegistry observationRegistry() {
return TestObservationRegistry.create();
}
@Bean
SimpleTracer simpleTracer() {
return new SimpleTracer();
}
}
}我們還可以通過以下示例測試來測試我們的 GreetingService:
import static io.micrometer.tracing.test.simple.TracerAssert.assertThat;
// ...
@Autowired
GreetingService service;
@Autowired
SimpleTracer tracer;
// ...
@Test
void testTracingForGreeting() {
service.sayHello();
assertThat(tracer)
.onlySpan()
.hasNameEqualTo("greeting-service#say-hello")
.isEnded();
}6. 結論
本文介紹了 Micrometer 觀察 API 以及其在 Spring Boot 3 中的集成。我們瞭解到 Micrometer 是一個與供應商無關的觀測 API,而 Micrometer Tracing 是其擴展。 此外,我們還確定了 Actuator 提供了一組預配置的觀測和跟蹤,並且默認情況下,用於測試的觀測性自動配置已禁用。