介紹
生產服務應用可觀測性在當下比較流行的方案,其中出現了大量高性能、開箱即用、易上手的的開源產品,大大豐富了在可觀測性領域產品的多樣性,本文講述基于OTLP協議推送Java項目遙測數據(日志、指標、鏈路)到后端存儲服務,整體架構如下:
Opentelemetry:基于Javaagent代理使用探針技術抓取日志、指標、鏈路等遙測數據,通過OTLP協議推送到后端存儲;
Quickwit:日志與鏈路數據存儲后端,提供數據索引器和搜索器核心功能;
Jaeger:基于Quickwit鏈路索引數據,提供查詢Trace服務數據跟蹤層級視圖;
Prometheus:服務運行指標與系統指標數據采集存儲服務;
Grafana:提供強大的可視化圖表,并支持眾多服務插件與數據源訪問,可集成日志查詢、Trace跟蹤層級、指標數據展示等;
OpenTelemetry
OpenTelemetry就是一種為應用程序代碼進行插樁的機制,是一個可觀測性框架和工具包, 旨在創建和管理遙測數據,它的目的是幫助使系統變得可觀測,如鏈路、?指標和日志。 重要的是,OpenTelemetry 是供應商和工具無關的,這意味著它可以與各種可觀測性后端一起使用, 括?Jaeger?和?Prometheus?這類開源工具以及商業化產品。
OpenTelemetry 不是像 Jaeger、Prometheus 或其他商業供應商那樣的可觀測性后端。 OpenTelemetry 專注于遙測數據的生成、采集、管理和導出。 OpenTelemetry 的一個主要目標是, 無論應用程序或系統采用何種編程語言、基礎設施或運行時環境,你都可以輕松地將其儀表化。 重要的是,遙測數據的存儲和可視化是有意留給其他工具處理的。
OpenTelemetry支持多種編程語言零代碼插樁模式,在應用或服務的“邊緣”捕獲遙測數據;本文演示通過零代碼插樁模式,通過opentelemetry-javaagent動態注入字節碼以從Java庫和Java框架中捕獲遙測數據,并推送到日志、鏈路、指標數據存儲平臺;
opentelemetry使用詳情參見官文文檔: Java zero-code instrumentation | OpenTelemetry
opentelemetry-javaagent.jar包開源版本下載: https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases
采集Java日志、鏈路、指標
在Java項目的jvm啟動參數中,添加otel代理配置和集成Javaagent代理程序包:-javaagent:D:\\test\\opentelemetry-javaagent.jar,通過探針技術抓取日志內容(logs)和跟蹤鏈路跨度數據(traces + span),向指定endpoint端點發送采集數據包;(本示例中使用opentelemetry-javaagent - version: 2.13.3版本,如遇javaagent配置不生效或異常,可以使用該版本調試)
-javaagent:D:\\test\\opentelemetry-javaagent.jar
-Dotel.service.name=customer
-Dotel.logs.exporter=otlp
-Dotel.exporter.otlp.endpoint=http://192.168.1.3:7281
-Dotel.exporter.otlp.protocol="grpc"
-Dotel.traces.exporter=otlp
-Dotel.metrics.exporter=otlp
-Dotel.exporter.otlp.metrics.protocol="http/protobuf"
-Dotel.exporter.otlp.metrics.endpoint=http://192.168.1.3:9090/api/v1/otlp/v1/metrics
-Dotel.metric.export.interval=30000
-Dotel.exporter.otlp.insecure=true
otel.exporter.otlp.endpoint指向的endpoint數據攝取接收器Quickwit日志存儲,Quickwit只支持otlp協議gRPC數據傳輸模式,將logs和traces采集數據通過導出器導出到Quickwit中存儲;
otel.exporter.otlp.metrics.endpoint指向的endpoint遙測指標數據接收器Pormetheus存儲,將metrics遙測指標樣本數據通過導出器導出到Prometheus遠程寫入器中;
注意,如果將-Dotel.metrics.exporter=none,none則表示不啟用Metrics指標數據導出器(通常是導出到Prometheus平臺),一般項目中會啟用Prometheus主動通過pull拉取模式,獲取Java項目(如: SpringBoot)中開啟的遙測數據端點,將采集樣本數據寫入到Prometheus中存儲;但如果需要啟用opentelemetry的代理模式,并通過otlp協議的metrics導出器導出遙測數據,并由Prometheus平臺接收遠程otlp數據,則將otel.metrics.exporter設置成otlp或pormetheus;
目前Pormetheus不支持otlp協議下grpc傳輸數據遠程寫入,只支持protobuf數據接收與解析,需要單獨設置otlp下metrics的protocol傳輸協議為:"http/protobuf";
同時還需要在Prometheus平臺開啟遠程寫入otlp接收器,在prometheus啟動參數中填加“ --web.enable-remote-write-receiver --web.enable-otlp-receiver”,啟用后otlp接收器endpoint為: /api/v1/otlp/v1/metrics;
完整Prometheus的啟動命令,如下:
./prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/prometheus \
--web.enable-remote-write-receiver \
--web.enable-otlp-receiver
關于Prometheus平臺遠程寫入OTLP接收器說明,參見官文文檔:HTTP API | Prometheus
Idea配置Javaagent代理
在處以已存在的springboot項目為例,該示例演示了一個完整跨服務請求鏈路:客戶端》網關》生產者,詳情請參見《 GitCode下載示例項目》;
在Idea》Run/Debug Configurations》Build and run》VM options,對CustomerCloudApplication、GatewayCloudApplication、ProducerCloudApplication三個SrpingBoot項目啟動入口JVM參數上,填入前一章節:-javaagent + otel參數配置;
并在Idea中分別先后啟動Springboot測試應用程序:CustomerCloudApplication、GatewayCloudApplication、ProducerCloudApplication;
啟動過程中,注意觀察控制臺是否有異常日志信息或endpoint端點網絡不通等信息,如有(注意:容易在otel.exporter.otlp.protocol配置上出錯,目前quickwit只支持基于otlp協議下的grpc端點服務,其它端點模式目前暫不支持),請先解決網絡通暢問題;
在瀏覽器中多次請求測試URL:http://localhost:8083/api/customer,在對應接口中輸出日志和traceID數據,提取控制臺中,最后條記錄的traceId=e16613fb04ebd7cb139de1039dc575ee,在Quickwit中進行日志和跟蹤鏈路查詢(后續章節講解安裝與使用);
安裝Quickwit
Quickwit原生支持opentelemetry協議(OTLP),默認Quickwit已開啟gRPC端點服務,用來接收來自Opentelemetry收集轉發的跨度數據信息;
Quickwit通過單獨的端口“ 7281”來接收客戶端的gRPC數據,Quickwit默認支持以下端口開放,參見官方文檔: Ports configuration | Quickwit
需要注意的是,根據官方文檔描述,目前無法獨立更改配置這些端口,如遇端口沖突,請注意排查;
如果采用Docker安裝的Quickwit服務,則記得添加7281端口配置來支持gRPC模式,或可參考已發布文章《 Docker安裝Quickwit日志搜索引擎》;:
# 創建卷綁定目錄
mkdir -p ~quickwit_data# 安裝容器
docker run \-p 7280:7280 \-p 7281:7281 \--name quickwit \--rm \-v ~/quickwit/data:/quickwit/qwdata \quickwit/quickwit:latest run
安裝Quickwit后,默認已開啟gRPC功能,會在Quickwit啟動過程中,檢查是否存在otel-logs-v0_7索引庫(用于收集otlp協議推送的索引數據)和otel-traces-v0_7索引庫(用于收集跟蹤鏈路的跨度數據),如果不存在,則會自動創建此索引庫。
如果不想啟用默認創建內置otel-logs-v0_7索引庫和otel-traces-v0_7索引庫,則可通過以下任意一種方式關閉該功能;
- 在啟動Quickwit時將環境變量QW_ENABLE_OTLP_ENDPOINT設置成false
- 在Quickwit服務的config.yaml配置文件中將enable_otlp_endpoint設置成false,如下:
# ... Indexer configuration ...
indexer:enable_otlp_endpoint: false
注意:不使用默認創建的otel-logs-v0_7索引庫和otel-traces-v0_7索引庫,自建日志和鏈路數據索引庫,索引結構需要按照otlp協議輸出標準的字段結構創建,并在otlp協議傳輸中指定數據推送索引;
瀏覽器訪問Quickwit控制臺:http://docker_ip:7080,在Quickwit》Query editor中,選擇IndexId:otle-logs-v0_7索引日志庫,查詢框中輸入:trace_id:e16613fb04ebd7cb139de1039dc575ee(java日志中打印的traceID),點擊RUN查詢此日志跟蹤ID所檢索匹配的日志記錄;
查詢出匹配此trace_id的三條日志,通過body字段中存儲的采集日志內容,能識別分別來源于:CustomerCloudApplication、GatewayCloudApplication、ProducerCloudApplication程序;
整個請求流程為: 瀏覽器》客戶端》網關代理》生產端,如下:
- 在瀏覽器中向客戶端程序發起http請求:http://localhost:8083/api/customer
- 客戶端程序CustomerCloudApplication控制器API接收到瀏覽器請求后,在此API方法中又請求到gateway網關程序(輸出日志:http request customer ...)
- gateway網關程序ProducerCloudApplication將收到的客戶端請求,代理轉發到生產端程序(輸出日志:route customer to producer,route id: producer, http request url http://127.0.0.1:8081/api/producer)
- 生產端程序ProducerCloudApplication控制器API接收到客戶端請求后,并返回響應結果(輸出日志:http request producer ...)
- 生產端響應通過gateway網關返回到客戶端中,客戶端將響應結果再返回給瀏覽器,整個請求鏈路結束
選擇IndexId:otle-traces-v0_7索引日志庫,查詢框中輸入:trace_id:e16613fb04ebd7cb139de1039dc575ee(java日志中打印的traceID),點擊RUM查詢此日志跟蹤ID所匹配的跟蹤鏈路跨度數據,由于數據結構比較復雜并且上報跨度記錄較多,Quickwit中沒有可直觀查看的可視化層級視圖,只能查看原始跟蹤鏈路跨度數據;
因此還需要借助第三方工具來展示完整的跟蹤鏈路層級視圖,目前Quickwit官方推薦搭配Jaeger,做為traces數據可視化平臺;
以Quickwit做為后端存儲工具,Jaeger做為搜索和跟蹤鏈路數據的前端UI,集成方式請參見官方文檔: Plug Quickwit to Jaeger | Quickwit;
安裝Jaeger
通過docker命令快速安裝Jaeger-query服務容器,或可參考已發布文章《 Docker安裝Jaeger鏈路追蹤》;
docker run --rm --name jaeger-qw \-e SPAN_STORAGE_TYPE=grpc \-e GRPC_STORAGE_SERVER=host.docker.internal:7281 \-p 16686:16686 \-p 4317:4317 \-p 4318:4318 \jaegertracing/jaeger-query:latest
注意:host.docker.internal指docker服務引擎本身的網絡綁定地址,如果Jaeger和Quickwit安裝在不同的服務或docker環境下,請更改為Quickwit服務IP地址;
其中16686為UI訪問與服務http restapi請求端口,4317為otlp協議gRPC數據傳輸端口,4318為otlp協議http數據傳輸端口;
待Jaeger-query容器服務安裝啟動后,在瀏覽器中訪問:http://jaeger_ip:16686,在Jaeger UI中查看traces跟蹤鏈路數據層級視圖效果,如下:
Grafana集成Jaeger
也可以通過在Grafana上安裝Jaeger數據源插件,將跟蹤鏈路查詢功能集成到Grafana中,再同Grafana集成的Quickwit日志搜索功能,一起來搭配使用,共建一個日志和鏈路管理平臺;
Grafana集成Jaeger方式比較簡單,在Connections》Add new connection中搜索jaeger,點擊數據源,進入安裝頁安裝,安裝后直接配置jaeger》Connection》url:http://jaeger_ip:16686,保存無錯誤提示即可;
安裝Jaeger數據插件后,在Explore頁面中,選擇jaeger數據源,直接輸入TraceID即可查詢匹配該跟蹤ID的所有鏈路數據,并以調用鏈路層級結構視圖進行詳細展示;
Grafana集成Quickwit
通過Grafana集成Quickwit日志搜索引擎服務,來管理日志存儲與日志檢索,在Grafana中安裝Quickwit數據插件也是非常的簡單,在Connections》Add new connection》搜索quickwit,點擊quickwit數據源,進入安裝頁面安裝,安裝后進行集成配置,在quickwit-quickwit-datasource》HTTP》URL中輸入:http://quickwit_ip:7280/api/v1,此quickwit_ip為目標quickwit服務所在的IP地址;
在Index settings中指定需要配置查詢的IndexID:otel-logs-v0_7 索引庫,otel-logs-v0_7是quickwit日志引擎服務默認開啟的gRPC服務日志數據上傳索引庫,也可自行根據otel-logs-v0_7索引結構創建自定義的項目日志索引庫,此處IndexID按需要修改即行;
在Editor settings》Default logs limit中將默認返回100條日志數量,修改為200條;
點擊Data links》+Add 的按鈕,添加日志數據結構中指定字段的超鏈接,設置該字段鏈接到Grafana已集成的jaeger數據源中,設置如下:
Field:trace_id
Query:${__value.raw}
Internal link:jaeger (數據源)
配置完畢,點擊Save & test按鈕,保存無錯誤提示即完成;
在Grafana》Explore界面中,選擇quickwit數據源,搜索任意時間段有效上傳索引庫日志,在返回列表中,點擊指定日志行,展開顯示詳細字段與數據,在最后的trace_id字段值(此trace_id即為日志中打印的跟蹤埋點ID)后邊,有一個"jaeger"按鈕,點擊后跳轉到jaeger頁面,并根據此TraceID值查詢所匹配的跟蹤鏈路日志,通過鏈路調用層級視圖,清晰的展示該跟蹤ID所執行的跨度指標數據;
安裝Prometheus
以Prometheus做為項目的遙測指標數據攝取和存儲服務,通過OTLP傳輸協議遠程寫入,因此還需要安裝Prometheus服務,使用Docker命令安裝,或參考已發布文章《 Docker安裝Prometheus監控平臺》;
# 創建卷綁定目錄
mkdir -p ~/prometheus_data# 目錄授權
chomd 777 prometheus_data# 創建容器
docker run --name prometheus \-c 2 -m 1g --memory-swap=1536m \-p 9090:9090 \-v ~/prometheus_data:/prometheus \prom/prometheus:latest \--web.enable-remote-write-receiver \--web.enable-otlp-receiver
安裝成功后,通過瀏覽器訪問:http://docker_id:9090,進入主頁面后即可查詢攝取的指標數據;
Grafana集成Prometheus
在Connections>Add new Connection 頁面搜索prometheus插件,點擊右上角Add new data source安裝數據源,
prometheus數據源安裝如無其它鑒權要求,則配置非常簡單,只需根據實際安裝服務地址填入到Prometheus server URL配置,如下:
確認無誤后,點擊Save & test按鈕,如無錯誤提示,則prometheus數據源安裝成功;
Jaeger集成Prometheus
此jaeger集成Prometheus,是指在Grafana可視化平臺 Home》Connections》Data source》jaeger 配置頁面下,增加jaeger額外Trace to metrics鏈接查詢,通過該配置支持在jaeger跨度層級視圖中,跳轉到prometheus數據源中通過promql語句查詢指定條件metrics數據展示;
Data source: prometheus # 數據源名
Span start time shift: -2m #跨度起始時間,往前推2分鐘
Span end time shift: 2m #跨度結速時間,往后推2分鐘
Tags: service.instance.id=instance # 跨度數據標簽名,格式:跨度字段名(來源Span Attributes)=指標查詢名
Link Label:
cpu time:rate(jvm_cpu_time_seconds_total{$__tags}[1m]) * 60? ?#查詢每分鐘CPU使用率
memory bytes:sum by(id) (increase(jvm_memory_used_bytes{$__tags}[1m]))? ? #查詢每分鐘內存使用
thread count:increase(jvm_thread_count{$__tags}[1m])? ? #查詢每分鐘線程數
http request:sum by(http_route) (rate(http_server_request_duration_seconds_count{$__tags}[1m]) * 60) ? #查詢每分鐘請求數
jaeger跟蹤鏈路視圖中跨度屬性Span Attributes,每個跨度級別均包含該 Attributes相關字段屬性;
在Jaeger跟蹤鏈路視圖中跨度中,點擊每層的超鏈接圖標,即可展示已配置的幾個指標查詢選項,選擇任意項則可以通過預配的promql查詢語句,獲取該跨度時間范圍段遙測指標數據;
如:選擇 memory btyes 查詢顯示該跨度時間范圍段Jvm使用內存的數據圖表(promql查詢采集到Java項目的jvm_memory_used_bytes指標)
參考:
Grafana,Loki,Tempo,Prometheus,Agent搭建日志鏈路監控平臺_grafana tempo-CSDN博客
Docker安裝Prometheus監控平臺_docker上安裝prometheus-CSDN博客
Grafana集成Quickwit插件-CSDN博客
Docker安裝Jaeger鏈路追蹤平臺-CSDN博客