本文介紹如何使用 OpenTelemetry 對 Nginx 進行鏈路追蹤。 Nginx 是一個高性能、輕量級的開源 Web 服務器和反向代理服務器,支持通過模塊以擴展其功能。Nginx OTel 模塊支持采集 Nginx 的調用鏈并通過 OpenTelemetry Collector 轉發上報至可觀測鏈路 OpenTelemetry 版。
使用限制
Nginx OTel 模塊目前僅支持 gRPC 方式上報,不支持 HTTP 方式上報。
Nginx OTel 模塊暫不支持設置 gRPC 鑒權 Token,因此您需要部署 OpenTelemetry Collector。將 Nginx OTel 采集到的 Nginx 調用鏈通過 OpenTelemetry Collector 轉發上報至可觀測鏈路 OpenTelemetry 版。詳細步驟,請參見三、部署 OpenTelemetry Collector。
前提條件
登錄ARMS控制臺,在左側導航欄單擊接入中心。
在服務端應用區域單擊OpenTelemetry卡片。
在彈出的OpenTelemetry面板中選擇數據需要上報的地域。
說明初次接入的地域將會自動進行資源初始化。
選擇連接方式和上報方式,然后復制接入點信息。
連接方式:若您的服務部署在阿里云上,且所屬地域與選擇的接入地域一致,推薦使用阿里云內網方式,否則選擇公網方式。
上報方式:根據客戶端支持的協議類型選擇gRPC協議上報數據。
接入步驟
一、下載 Nginx OTel 模塊
Alibaba Cloud Linux、RedHat、RHEL 及其衍生版本
sudo yum install nginx-module-otel
Debian、Ubuntu 及其衍生版本
sudo apt install nginx-module-otel
二、啟用 Nginx OTel 模塊
若要為 Nginx 啟用鏈路追蹤,您需要在 Nginx 主配置文件/etc/nginx/nginx.conf
中加載 OTel 模塊并添加配置項。關于 OTel 模塊的更多參數配置信息,請參見ngx_otel_module 模塊文檔。
全局配置:為所有 HTTP 請求開啟鏈路追蹤。
說明請替換配置中的兩個變量:
${OTEL_COLLECTOR_GRPC_RECEIVER_ENDPOINT}
:OpenTelemetry Collector gRPC 上報點。此上報點為您部署的 OpenTelemetry Collector 的 gRPC 上報點,例如localhost:4317
,而不是前提條件中獲取的可觀測鏈路 OpenTelemetry 版的接入點。${SERVICE_NAME
:應用名稱。此名稱將會作為 Nginx 的應用名稱在可觀測鏈路 OpenTelemetry 版控制臺中展示。
load_module modules/ngx_otel_module.so; # 加載 ngx_otel_module ... http { ... otel_exporter { endpoint ${OTEL_COLLECTOR_GRPC_RECEIVER_ENDPOINT}; # OpenTelemetry Collector 的上報地址,例如 localhost:4317 } otel_trace on; # 開啟鏈路追蹤 otel_service_name ${SERVICE_NAME} # 應用名 otel_trace_context inject; # 向下游服務注入Trace上下文 ... }
單個 Location 配置:為單個 Location 開啟鏈路追蹤。
說明請替換配置中的兩個變量:
${OTEL_COLLECTOR_GRPC_RECEIVER_ENDPOINT}
:OpenTelemetry Collector gRPC 上報點。此上報點為您部署的 OpenTelemetry Collector 的 gRPC 上報點,例如localhost:4317
,而不是前提條件中獲取的可觀測鏈路 OpenTelemetry 版的接入點。${SERVICE_NAME
:應用名稱。此名稱將會作為 Nginx 的應用名稱在可觀測鏈路 OpenTelemetry 版控制臺中展示。
load_module modules/ngx_otel_module.so; # 加載 ngx_otel_module ... http { otel_exporter { endpoint ${OTEL_COLLECTOR_GRPC_RECEIVER_ENDPOINT}; # OpenTelemetry Collector 的上報地址,例如 localhost:4317 } server { listen 127.0.0.1:80; location /hello { otel_trace on; # 只為 127.0.0.1:80/hello 開啟鏈路追蹤 otel_service_name ${SERVICE_NAME} # 應用名 otel_trace_context inject; # 向下游服務注入Trace上下文 ... } } }
三、部署 OpenTelemetry Collector
下文以 Docker 方式為例,介紹如何部署 OpenTelemetry Collector。更多部署方式,請參見下載并部署OpenTelemetry Collector。
創建
opentelemetry-config.yaml
文件,并將下面的內容拷貝至文件。該文件用于定義和配置OpenTelemetry Collector的行為和功能,包括如何接收、處理和導出數據。
說明請將
${GRPC_ENDPOINT}
和${GRPC_ENDPOINT_TOKEN}
替換為前提條件中獲取的 gRPC 接入點和鑒權 Token。receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 exporters: otlp: endpoint: ${GRPC_ENDPOINT} tls: insecure: true headers: "Authentication": "${GRPC_ENDPOINT_TOKEN}" processors: batch: service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [otlp]
啟動 OpenTelemetry Collector。
docker run -v $(pwd)/opentelemetry-config.yaml:/etc/otelcol-contrib/config.yaml otel/opentelemetry-collector-contrib:0.105.0
四、查看 Nginx 調用鏈
完成以上配置并重啟 Nginx 后,您可向 Nginx 發送請求,以生成調用鏈。然后登錄可觀測鏈路 OpenTelemetry 版控制臺,查看由 OpenTelemetry 生成的 Nginx 調用鏈。
在應用列表頁面查看 Nginx 應用。
在調用鏈分析頁面打開 Nginx 的調用鏈,查看請求耗時、客戶端 IP、 HTTP 狀態碼等信息。如果您的后端服務也接入了可觀測鏈路 OpenTelemetry 版,您將會看到串聯在一起的 Nginx 與后端服務調用鏈。
實踐教程
接下來將通過案例演示如何采集 Nginx 及后端應用的調用鏈,并上報至可觀測鏈路 OpenTelemetry 版。
一、準備工作
確認已安裝 Git、Docker 和 Docker Compose。
二、項目結構
nginx-otel-demo
│
├── docker-compose.yml # Docker Compose 配置文件
│
├── nginx_conf/ # nginx 配置文件
│ ├── default.conf
│ └── nginx.conf
│
├── otel_conf/ # OpenTelemetry Collector 配置文件
│ └── config.yaml
│
└── backend/ # Node.js 后端服務
├── Dockerfile
├── main.js
├── package.json
└── package-lock.json
創建文件夾:
mkdir nginx-otel-demo && cd nginx-otel-demo
mkdir -p nginx_conf otel_conf backend
三、創建 Nginx 配置
創建 Nginx 主配置文件
nginx.conf
。cat << 'EOF' > nginx_conf/nginx.conf load_module modules/ngx_otel_module.so; user nginx; worker_processes auto; error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; otel_exporter { endpoint otel-collector:4317; } otel_trace on; otel_trace_context inject; otel_service_name nginx; include /etc/nginx/conf.d/*.conf; } EOF
創建 Nginx 配置文件
default.conf
。cat << 'EOF' > nginx_conf/default.conf server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } # 在這里添加 location /hello { proxy_pass http://backend-api:7001/hello; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } EOF
四、創建 OpenTelemetry Collector 配置
創建 OpenTelemetry Collector 配置文件,該配置文件定義了數據如何被接收、處理和上報。
請將${GRPC_ENDPOINT}
和${GRPC_ENDPOINT_TOKEN}
替換為前提條件中獲取的 gRPC 接入點和鑒權 Token。
cat << 'EOF' > otel_conf/config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
exporters:
otlp:
endpoint: ${GRPC_ENDPOINT}
tls:
insecure: true
headers:
"Authentication": "${GRPC_ENDPOINT_TOKEN}"
processors:
batch:
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
EOF
五、創建后端服務(Node.js)
創建 package.json 文件。文件描述了項目的配置信息,包括項目名稱、版本、依賴項等。
cat << 'EOF' > backend/package.json { "name": "backend", "version": "1.0.0", "main": "index.js", "scripts": {}, "keywords": [], "author": "", "license": "ISC", "description": "", "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/auto-instrumentations-node": "^0.52.0", "axios": "^1.7.7", "express": "^4.21.1" } } EOF
創建 main.js 文件,包含一個基本的 Express 框架 Web 應用程序。
cat << 'EOF' > backend/main.js "use strict"; const axios = require("axios").default; const express = require("express"); const app = express(); app.get("/", async (req, res) => { const result = await axios.get("http://localhost:7001/hello"); return res.status(201).send(result.data); }); app.get("/hello", async (req, res) => { console.log("hello world!") res.json({ code: 200, msg: "success" }); }); app.use(express.json()); app.listen(7001, () => { console.log("Listening on http://localhost:7001"); }); EOF
創建 Dockerfile 文件。
cat << 'EOF' > backend/Dockerfile FROM node:20.16.0 WORKDIR /app COPY package*.json ./ RUN npm install COPY . . ENV OTEL_TRACES_EXPORTER="otlp" ENV OTEL_LOGS_EXPORTER=none ENV OTEL_METRICS_EXPORTER=none ENV OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc ENV OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://otel-collector:4317" ENV OTEL_NODE_RESOURCE_DETECTORS="env,host,os" ENV OTEL_SERVICE_NAME="ot-nodejs-demo" ENV NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register" EXPOSE 7001 CMD ["node", "main.js"] EOF
六、創建 Docker Compose 文件
該文件定義了一個多容器應用程序的配置,包括 Nginx 反向代理、OpenTelemetry Collector 和 Node.js 后端服務,以及它們之間的網絡連接和端口映射。
cat << 'EOF' > docker-compose.yml
version: "3"
services:
nginx:
image: nginx:1.27.2-alpine-otel # 默認包含 opentelemetry 模塊的 nginx 鏡像
volumes:
- ./nginx_conf/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx_conf/default.conf:/etc/nginx/conf.d/default.conf:ro
ports:
- "80:80"
networks:
- nginx-otel-demo
otel-collector:
image: otel/opentelemetry-collector-contrib:latest
volumes:
- ./otel_conf/config.yaml:/etc/otelcol-contrib/config.yaml # 掛載 OpenTelemetry Collector 配置文件
ports:
- "4317:4317" # OTLP gRPC receiver
networks:
- nginx-otel-demo
backend-api:
build:
context: ./backend
dockerfile: Dockerfile
environment:
- NODE_ENV=production
ports:
- "7001:7001"
networks:
- nginx-otel-demo
networks:
nginx-otel-demo:
driver: bridge
EOF
七、啟動服務
在 nginx-otel-demo 目錄中執行以下命令。
docker compose up -d
預期輸出:
訪問應用。
curl http://localhost:80/hello
預期輸出:
{"code":200,"msg":"success"}
登錄可觀測鏈路 OpenTelemetry 版控制臺查看 Nginx 及后端服務的調用鏈。
在本例中,Nginx 在應用列表頁面的名稱為 nginx,后端應用名稱為 ot-nodejs-demo。
常見問題
在 Nginx 配置文件中添加 Nginx OTel 模塊配置后,Nginx 啟動失敗。
請使用
nginx -t
命令檢查 Nginx 配置是否正確,或查看 Nginx 日志中的錯誤信息。sudo tail -n 50 /var/log/nginx/error.log
啟用 Nginx OTel 模塊后,在可觀測鏈路 OpenTelemetry 版控制臺沒有看到 Nginx 的調用鏈。
請檢查 Nginx 配置中 otel_exporter.endpoint 是否配置正確。該地址由 OpenTelemetry Collector 地址以及 gRPC 接收器端口組成,例如
localhost:4317
??赏ㄟ^查看 Nginx 日志確認是否配置正確,當出現如下報錯時,說明 otel_exporter.endpoint 未配置正確。Nginx 的調用鏈無法與其他應用串聯。
請確保 Nginx 配置中添加了
otel_trace_context inject;
,并確認其他應用使用的鏈路透傳協議與 Nginx 的透傳協議是否相同。Nginx OTel 模塊使用 OpenTelemetry W3C 作為透傳協議,這需要其他應用也要使用 OpenTelemetry W3C 透傳協議才能串聯。Nginx OTel 插件模塊是否會對 Nginx 的性能產生影響?
Nginx OTel 插件模塊為 Nginx 原生模塊,官方提示該模塊對 Nginx 性能的影響限制在10-15%。詳細信息,請參見NGINX Native OpenTelemetry (OTel) Module。