將Java應用可觀測資料投遞至雲資料庫 ClickHouse 企業版
本文介紹如何將Java應用的可觀測資料投遞至雲資料庫 ClickHouse 企業版,並通過一站式可觀測服務進行分析,旨在協助開發人員和營運人員即時監控應用效能、提升問題解決效率。
前提條件
雲資料庫 ClickHouse 企業版執行個體已開啟一站式可觀測服務。
操作步驟
本文樣本中,將在同一台ECS上部署商務服務和Otel Collector。生產環境下,建議獨立部署商務服務和Otel Collector。
步驟一:部署Otel Collector
-
配置ECS執行個體。
-
購買ECS執行個體。建議購買時分配公網IP,使ECS具備公網訪問能力。
-
將ECS IP地址添加到雲資料庫ClickHouse的白名單中。
-
私網IP:如果ECS執行個體與雲資料庫 ClickHouse 企業版執行個體位於同一VPC,可以將ECS的私網IP地址添加到白名單中,以下操作中雲資料庫ClickHouse執行個體的Endpoint使用VPC地址。
-
公網IP:如果ECS執行個體與雲資料庫 ClickHouse 企業版執行個體私網不通,可以將ECS的公網IP地址添加到白名單中,以下操作中雲資料庫ClickHouse執行個體的Endpoint使用外網地址。
您可以串連ECS執行個體,使用以下命令測試ECS與雲資料庫ClickHouse執行個體之間的連通性,若返回
Ok.代表串連正常。curl http://cc-xxxxxxx-clickhouse.clickhouseserver.pre.rds.aliyuncs.com:8123 -
-
-
串連ECS執行個體,依次執行以下命令,安裝otelcol-contrib。
mkdir llm-demo cd llm-demo wget -O otelcol-contrib.rpm https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.136.0/otelcol-contrib_0.136.0_linux_amd64.rpm yum install otelcol-contrib.rpm -
配置Otel Collector,允許通過grpc和HTTP協議接收可觀測資料,並通過HTTP協議投遞至雲資料庫ClickHouse執行個體。
複製以下命令並修改相關配置:
-
在receivers地區:建議將otlp receiver的endpoint替換為Otel Collector服務的endpoint。
-
在exporters地區:
-
配置雲資料庫ClickHouse執行個體的串連資訊,包括endpoint、username和password。
-
配置雲資料庫ClickHouse執行個體儲存可觀測資料的庫名和表名,包括database、traces_table_name、logs_table_name和metrics_tables。
-
cat > /etc/otelcol-contrib/config.yaml << EOF receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: timeout: 5s send_batch_size: 5000 exporters: clickhouse: endpoint: http://cc-xxxxxx-clickhouse.clickhouseserver.pre.rds.aliyuncs.com:8123?dial_timeout=10s&compress=lz4&async_insert=1 username: test password: password # ttl: 72h traces_table_name: otel_traces logs_table_name: otel_logs metrics_tables: gauge: name: otel_metrics_gauge sum: name: otel_metrics_sum summary: name: otel_metrics_summary histogram: name: otel_metrics_histogram exponential_histogram: name: otel_metrics_exp_histogram create_schema: false timeout: 5s database: clickobserve_service sending_queue: queue_size: 1000 retry_on_failure: enabled: true initial_interval: 5s max_interval: 30s max_elapsed_time: 300s service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [clickhouse] metrics: receivers: [otlp] processors: [batch] exporters: [clickhouse] logs: receivers: [otlp] processors: [batch] exporters: [clickhouse] EOF -
-
啟動Otel Collector。
service otelcol-contrib restart
步驟二:建立Java應用
本節以一個簡單的Springboot隨機擲骰子服務為例,介紹應用建立過程。
-
配置Java環境。
-
本樣本目錄命名為
java-simple,初始化後目錄結構參見下方:java-simple ├── app │ ├── build.gradle.kts │ └── src │ ├── main │ │ ├── java │ │ │ └── org │ │ │ └── example │ │ │ └── App.java │ │ └── resources │ └── test │ ├── java │ │ └── org │ │ └── example │ │ └── AppTest.java │ └── resources ├── gradle │ ├── libs.versions.toml │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle.kts -
在
java-simple目錄下修改或建立以下檔案:修改build.gradle.kts
plugins { id("java") id("org.springframework.boot") version "3.0.6" id("io.spring.dependency-management") version "1.1.0" } sourceSets { main { java.setSrcDirs(setOf(".")) } } repositories { mavenCentral() } dependencies { implementation("org.springframework.boot:spring-boot-starter-web") }修改App.java
package org.example; import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication app = new SpringApplication(App.class); app.setBannerMode(Banner.Mode.OFF); app.run(args); } }建立RollController.java
package org.example; import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class RollController { private static final Logger logger = LoggerFactory.getLogger(RollController.class); @GetMapping("/rolldice") public String index(@RequestParam("player") Optional<String> player) { int result = this.getRandomNumber(1, 6); if (player.isPresent()) { logger.info("{} is rolling the dice: {}", player.get(), result); } else { logger.info("Anonymous player is rolling the dice: {}", result); } return Integer.toString(result); } public int getRandomNumber(int min, int max) { return ThreadLocalRandom.current().nextInt(min, max + 1); } }
步驟三:配置OpenTelemetry Java Agent
-
下載OpenTelemetry Java Agent。
curl -L -O https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar -
配置環境變數。
export JAVA_TOOL_OPTIONS="-javaagent:/../opentelemetry-javaagent.jar" \ OTEL_TRACES_EXPORTER=otlp \ OTEL_METRICS_EXPORTER=otlp \ OTEL_LOGS_EXPORTER=otlp \ OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \ OTEL_EXPORTER_OTLP_ENDPOINT=http://<IP地址>:4318 \ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://<IP地址>:4318/v1/traces \ OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://<IP地址>:4318/v1/metrics \ OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://<IP地址>:4318/v1/logs \ OTEL_METRIC_EXPORT_INTERVAL=15000-
JAVA_TOOL_OPTIONS:修改為Java Agent的實際存放路徑。 -
Endpoint相關配置:
http://<IP地址>:4318中的IP地址,為Java應用可訪問的Otel Collector服務端點。 -
其他參數選擇,請參見properties-exporters。
-
步驟四:啟動並訪問Java應用
-
在專案應用目錄下依次執行以下命令,啟動應用。
在本樣本中,專案應用目錄為
../java-simple/app。gradle assemble java -jar ./build/libs/app.jar -
瀏覽器訪問
http://<IP地址>:8080/rolldice,IP地址為運行Java應用的伺服器IP地址。訪問成功後,頁面返回一個隨機數字,樣本如下。
5
步驟五:查詢與分析可觀測資料
-
在雲資料庫ClickHouse執行個體詳情頁左側導覽列單擊一站式可观测,根據頁面提示前往服務入口。
-
在首頁面上查詢並分析Java應用的可觀測資料。
在 HyperDX 平台的 Search 頁面,資料來源選擇 otel_traces,輸入 SQL 查詢語句
SELECT Timestamp, ServiceName as service, StatusCode as level, round(Duration / 1e6) as duration, SpanName,排序方式設為 Timestamp DESC。左側 Filters 面板可按 SpanName(如 GET /rolldice、PUBLISH 等)和 ServiceName(如 app、langgenius/dify)篩選。查詢結果以表格形式展示 Timestamp、service、level、duration、SpanName 等列,可查看各服務 Span 記錄的耗時詳情。