SkyWalking

SkyWalking 1. 分布式追踪与核心概念 SkyWalking 用于分析分布式应用的调用关系、延迟、错误和资源使用情况。以“网关 → 订单服务 → 库存服务 → 数据库”为例,可以从一个慢请求定位到具体的下游调用、数据库访问或应用代码。 概念 含义 使用要点 Service 一个逻辑应用,如

SkyWalking

1. 分布式追踪与核心概念

SkyWalking 用于分析分布式应用的调用关系、延迟、错误和资源使用情况。以“网关 → 订单服务 → 库存服务 → 数据库”为例,可以从一个慢请求定位到具体的下游调用、数据库访问或应用代码。

概念含义使用要点
Service一个逻辑应用,如 prod::orders-api同一应用的多个副本使用同一服务名
Service Instance服务的运行实例,如一个 Pod 或进程实例名需要区分副本,不能全部写成同一个固定值
Endpoint服务处理的操作,如 GET:/orders/{id}使用路由模板,避免订单号等动态值造成高基数
Trace一次分布式请求的追踪上下文多个进程通过上下文传播关联到同一个 Trace
Segment一个线程或执行上下文中的一组 Span跨进程、跨线程通过引用关联,不等于完整 Trace
Span一次操作的开始、结束、状态及标签常见类型为 Entry、Exit、Local

Trace ID 关联整条请求;Span ID 在所属 Segment 内使用,不能只拿 Span ID 在不同进程间关联。同步调用、线程池、异步任务和消息消费都有各自的传播机制,只有插件支持或正确使用 Toolkit,才能把上下游关联起来。

追踪系统适合回答“慢在哪一跳”“错误发生在哪个服务”“哪个依赖影响了入口”。服务指标用于观察趋势,Trace 用于分析具体请求,日志用于补充业务上下文,Profiling 用于进一步定位热点代码。平均响应时间不能代替 P95/P99,也不能把成功率指标直接当成经过业务定义的 SLO。

2. 架构、端口与版本

业务请求:客户端 → 网关 → 应用服务 → 数据库 / 缓存 / MQ
                         │ Agent 采集与上报
                         ▼
                    OAP Server
                    │       ▲
              写入/查询     │ 查询 API
                    ▼       │
                  存储 ← OAP ← UI ← 浏览器
  • Agent:为受支持的框架自动埋点,传递追踪上下文,采集应用指标和 Trace。
  • OAP:接收数据、聚合指标、分析拓扑、执行告警并读写存储。
  • 存储:保存 Trace、指标、日志、告警及管理数据。OAP 10.4 可使用 Elasticsearch、OpenSearch、BanyanDB 等后端。
  • UI:通过 OAP 的查询接口展示数据,不直接连接 Elasticsearch。
端口用途访问范围
11800/gRPCJava、Python、Go 等原生 Agent 上报;受支持的 OTLP/gRPC 接收应用到 OAP
12800/HTTPGraphQL 查询、健康检查及受支持的 HTTP 上报接口UI、管理网络及确有需要的 HTTP Agent
8080/HTTPUI管理网络或认证网关
1234/HTTPOAP 自监控 Prometheus 指标监控采集器
9200/HTTP(S)Elasticsearch APIOAP 和存储管理网络
9411/HTTP可选 Zipkin HTTP 接收仅启用该功能时使用
9412/HTTP可选 Zipkin 查询UI 到 OAP

本文使用 OAP/UI 10.4.0、Java Agent 9.4.0 作为配置示例,Elasticsearch 8.17.4 作为单机实验存储。这些是固定示例版本,不代表最新版本或生产环境升级目标。

OAP 与 Agent 独立发布,不要求版本号完全一致。OAP 10.x 的兼容表包含 Java Agent 8.x/9.x,具体框架、JDK、语言运行时仍需分别核对 Agent 支持列表。OAP 容器自带运行时,不能把应用 JDK、Agent 支持的 JDK 和 OAP 的运行 JDK 混为一谈;10.4.0 的官方 OAP Dockerfile 使用 JRE 25 基础镜像,二进制部署应按对应发行版要求准备 JDK。

3. Docker Compose 部署

3.1 目录与宿主机准备

以下是单机实验配置,所有文件放在 /data/skywalking。建议为宿主机预留至少 4 核、8 GiB 内存和足够磁盘空间,实际需求受业务流量、采样率和保留期影响。

install -d -m 0755 /data/skywalking/config
install -d -m 0750 /data/skywalking/elasticsearch
chown 1000:0 /data/skywalking/elasticsearch
cd /data/skywalking
sysctl vm.max_map_count

Elasticsearch 8.17 实验环境的 vm.max_map_count 至少需要达到 262144;已经更高时保持原值。需要持久调整时:

if [ "$(sysctl -n vm.max_map_count)" -lt 262144 ]; then
  printf 'vm.max_map_count=262144\n' > /etc/sysctl.d/90-skywalking-es.conf
  sysctl -p /etc/sysctl.d/90-skywalking-es.conf
fi

启用 SELinux 的主机需为绑定挂载目录设置适当容器标签或使用合适的挂载标记,不能靠关闭 SELinux 解决目录权限问题。

3.2 docker-compose.yml

将下面内容保存到 /data/skywalking/docker-compose.yml:

name: skywalking
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.17.4
    restart: unless-stopped
    environment:
      discovery.type: single-node
      xpack.security.enabled: "false"
      ES_JAVA_OPTS: "-Xms1g -Xmx1g"
    volumes:
      - /data/skywalking/elasticsearch:/usr/share/elasticsearch/data
    healthcheck:
      test:
        - CMD-SHELL
        - "curl -fsS 'http://localhost:9200/_cluster/health?wait_for_status=yellow&timeout=5s' >/dev/null"
      interval: 10s
      timeout: 10s
      retries: 18
      start_period: 40s
    logging:
      driver: json-file
      options:
        max-size: "20m"
        max-file: "3"

  oap:
    image: apache/skywalking-oap-server:10.4.0
    restart: unless-stopped
    depends_on:
      elasticsearch:
        condition: service_healthy
    environment:
      SW_STORAGE: elasticsearch
      SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
      SW_STORAGE_ES_INDEX_REPLICAS_NUMBER: "0"
      SW_HEALTH_CHECKER: default
      SW_TELEMETRY: prometheus
      SW_CORE_RECORD_DATA_TTL: "3"
      SW_CORE_METRICS_DATA_TTL: "7"
      JAVA_OPTS: "-Xms1g -Xmx1g"
    volumes:
      - /data/skywalking/config:/skywalking/ext-config:ro
    ports:
      - "127.0.0.1:11800:11800"
      - "127.0.0.1:12800:12800"
      - "127.0.0.1:1234:1234"
    logging:
      driver: json-file
      options:
        max-size: "20m"
        max-file: "3"

  ui:
    image: apache/skywalking-ui:10.4.0
    restart: unless-stopped
    depends_on:
      - oap
    environment:
      SW_OAP_ADDRESS: http://oap:12800
    ports:
      - "127.0.0.1:8080:8080"
    logging:
      driver: json-file
      options:
        max-size: "20m"
        max-file: "3"

实验存储没有对宿主机发布 9200。副本数 0 仅用于单节点验证,新建索引才按该配置创建;生产集群需要根据容错目标配置副本和节点数量。OAP 的 /skywalking/ext-config 会在启动时覆盖相应配置文件,只挂载需要覆盖的文件,不要用空目录遮住整个 /skywalking/config。

宿主机进程可以访问回环地址 127.0.0.1:11800;同一 Compose 网络中的应用使用 oap:11800。远程应用需要将映射改为宿主机的实际内网地址,并限制来源网络。容器中的 127.0.0.1 是容器自身,不能当作 OAP 地址。

3.3 启动与验收

cd /data/skywalking
docker compose config -q
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=100 elasticsearch oap ui
curl -fsS http://127.0.0.1:12800/healthcheck

OAP 初始化索引需要时间,刚启动时健康接口可能暂时失败。健康检查启用后,健康返回 200,不健康返回 503;未启用时可能返回 404。health checker 依赖 telemetry 模块,不能同时把 telemetry 关闭。

查询模块健康详情:

curl -fsS http://127.0.0.1:12800/graphql \
  -H 'Content-Type: application/json' \
  --data '{"query":"{checkHealth{score details}}"}'

score 为 0 表示健康,大于 0 表示存在不健康模块,负值表示尚未启动完成。GraphQL 的 HTTP 200 也可能包含 errors,需要检查响应正文。

检查存储与自监控指标:

docker compose exec -T elasticsearch \
  curl -fsS 'http://localhost:9200/_cluster/health?pretty'
docker compose exec -T elasticsearch \
  curl -fsS 'http://localhost:9200/_cat/indices?v'
curl -fsS http://127.0.0.1:1234/metrics -o /tmp/oap-metrics.txt
head -n 20 /tmp/oap-metrics.txt

本机浏览器访问 http://127.0.0.1:8080。服务器不在本机时,可以使用 SSH 隧道;下面的 22022 按实际 SSH 端口替换:

ssh -p 22022 -N -L 18080:127.0.0.1:8080 ops@skywalking.example.com

随后访问 http://127.0.0.1:18080。UI 能打开只说明前端可访问,完整验收还需要应用产生请求、出现服务指标并能查到 Trace。

4. Java、Spring Boot 与 Tomcat

4.1 安装 Java Agent

下载 Agent 9.4.0 发行包并校验 SHA-512:

install -d /data/skywalking/downloads
cd /data/skywalking/downloads
curl -fLO https://archive.apache.org/dist/skywalking/java-agent/9.4.0/apache-skywalking-java-agent-9.4.0.tgz
curl -fLO https://archive.apache.org/dist/skywalking/java-agent/9.4.0/apache-skywalking-java-agent-9.4.0.tgz.sha512
sha512sum -c apache-skywalking-java-agent-9.4.0.tgz.sha512
install -d /opt
tar -xzf apache-skywalking-java-agent-9.4.0.tgz -C /opt
test -f /opt/skywalking-agent/skywalking-agent.jar

保留 config、plugins 和 Agent 所需的其他目录,不能只复制一个 skywalking-agent.jar。应用用户需要读取 Agent 目录,并且能写入配置的 Agent 日志目录。

4.2 Spring Boot 启动

主机上的应用连接本机 Compose 暴露的端口:

export SW_AGENT_NAME='prod::orders-api'
export SW_AGENT_COLLECTOR_BACKEND_SERVICES='127.0.0.1:11800'
export SW_LOGGING_OUTPUT=CONSOLE
java -javaagent:/opt/skywalking-agent/skywalking-agent.jar \
  -jar /opt/orders-api/app.jar

也可以通过 JVM 系统属性配置:

java -javaagent:/opt/skywalking-agent/skywalking-agent.jar \
  -Dskywalking.agent.service_name='prod::orders-api' \
  -Dskywalking.collector.backend_service=127.0.0.1:11800 \
  -jar /opt/orders-api/app.jar

JVM 参数必须放在 -jar 前面。服务名、环境和分组统一规划,同一服务多个副本共用服务名;实例名可由 Agent 自动生成,Kubernetes 中可以使用 Pod 名。

4.3 Tomcat

在当前 Tomcat 实例的 $CATALINA_BASE/bin/setenv.sh 中加入:

export SW_AGENT_NAME='prod::web-tomcat'
export SW_AGENT_COLLECTOR_BACKEND_SERVICES='127.0.0.1:11800'
export CATALINA_OPTS="${CATALINA_OPTS:-} -javaagent:/opt/skywalking-agent/skywalking-agent.jar"

修改后重启 Tomcat。优先使用 CATALINA_OPTS,避免把 Agent 无差别加入所有 Java 子进程。直接运行 java -jar jenkins.war 时,也可以把 -javaagent 放在 -jar 前;观察 Jenkins 并不等于给其执行的所有构建任务自动添加 Agent。

4.4 插件与跨服务验证

Java Agent 的插件需要同时匹配框架类型和版本。可选插件按官方说明从 optional-plugins 放入 plugins,不要不加区分地启用全部插件。一次业务请求涉及的每个 Java 服务都要接入,数据库和 Redis 常见调用信息来自应用客户端插件,不要求在数据库进程里安装 Java Agent。

Dubbo 场景中分别为 Consumer 和 Provider 加载 Agent,使用不同服务名,再发起真实 RPC 调用。UI 中应能看到 Consumer → Provider 的关系和同一个 Trace。注册中心地址属于 Dubbo 应用配置,安装 Agent 不会替代 ZooKeeper/Nacos 的服务发现配置。

出现应用启动异常、类加载冲突或框架升级后没有 Span 时,先核对插件支持列表;不要通过降低整套应用的安全版本来迁就旧插件。

5. Docker 与 Kubernetes 应用接入

5.1 把 Agent 固定到应用镜像

构建上下文中准备经过校验的完整 skywalking-agent 目录和应用 app.jar:

FROM eclipse-temurin:21-jre
WORKDIR /app
COPY skywalking-agent/ /opt/skywalking-agent/
COPY app.jar /app/app.jar
ENV SW_LOGGING_OUTPUT=CONSOLE
ENTRYPOINT ["java", "-javaagent:/opt/skywalking-agent/skywalking-agent.jar", "-jar", "/app/app.jar"]

这里的 JDK 21 是应用示例版本,应与应用和 Agent 支持范围一致。Agent 升级通过构建新镜像完成,不在容器启动时临时下载。

5.2 Deployment 配置

下面假定 OAP Service 名为 skywalking-oap,位于 observability 命名空间,并已把上面的应用镜像推送到实际仓库:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: orders-api
  namespace: apps
spec:
  replicas: 2
  selector:
    matchLabels:
      app: orders-api
  template:
    metadata:
      labels:
        app: orders-api
    spec:
      containers:
        - name: app
          image: registry.example.com/orders-api:1.0.0
          ports:
            - name: http
              containerPort: 8080
          env:
            - name: SW_AGENT_NAME
              value: "prod::orders-api"
            - name: SW_AGENT_INSTANCE_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: SW_AGENT_COLLECTOR_BACKEND_SERVICES
              value: skywalking-oap.observability.svc:11800
            - name: SW_LOGGING_OUTPUT
              value: CONSOLE
          resources:
            requests:
              cpu: "250m"
              memory: "512Mi"
            limits:
              memory: "1Gi"
---
apiVersion: v1
kind: Service
metadata:
  name: orders-api
  namespace: apps
spec:
  selector:
    app: orders-api
  ports:
    - name: http
      port: 8080
      targetPort: http

命名空间须提前存在。资源值只是起点,应根据业务与 Agent 的额外开销调整。配置应用自身的 readiness/liveness/startup probe 时,使用应用的真实健康接口,不能把 Agent 到 OAP 的连接状态当成业务存活条件。

kubectl -n apps get pods -l app=orders-api
kubectl -n apps logs deployment/orders-api --tail=100
kubectl -n observability get svc skywalking-oap
kubectl -n observability get endpointslices \
  -l kubernetes.io/service-name=skywalking-oap

NetworkPolicy 需要允许应用到 OAP 的 11800/TCP;默认拒绝出站时还要允许 DNS。Token 通过 Secret 注入,不直接写入 Deployment 明文。

6. Python 与 Go

6.1 Python / Django

以下以 Python Agent 1.2.0 为例,其安装文档要求 Python 3.8+,实际 Python、Django 与依赖版本还要核对对应插件。建议使用项目虚拟环境,不向系统 Python 全局安装依赖:

python3 -m venv .venv
. .venv/bin/activate
python -m pip install 'apache-skywalking==1.2.0'
export SW_AGENT_NAME='prod::orders-python'
export SW_AGENT_COLLECTOR_BACKEND_SERVICES='127.0.0.1:11800'
export SW_AGENT_PROTOCOL=grpc
sw-python run python manage.py runserver 127.0.0.1:8000 --noreload

manage.py 属于已有 Django 项目;该命令只用于开发验证。项目设置中明确配置 ALLOWED_HOSTS,不要直接设置为 ['*']。

生产使用已安装的 Gunicorn 时,按 Agent 的 prefork 支持启动;mysite.wsgi 替换为实际模块:

sw-python run -p gunicorn mysite.wsgi:application \
  --workers 2 --bind 0.0.0.0:8000

Agent 不能只在 fork 前启动一套线程后就假定所有 worker 都正常上报。自动注入与手动 post_fork 启动方案选一种,不能重复初始化。

6.2 Go 编译期注入

只执行 go get 不会自动给一个现有二进制增加追踪。以下以 Go Agent 0.6.0 为例,需要下载并校验相同版本、匹配操作系统和 CPU 架构的 Agent 编译工具,将其放到 /opt/skywalking-go-agent;Go 工具链版本也要符合该 Agent 的支持范围。

在包含 main 包的源文件中导入:

import _ "github.com/apache/skywalking-go"

然后在项目根目录构建:

go get github.com/apache/skywalking-go@v0.6.0
go mod tidy
go build -toolexec=/opt/skywalking-go-agent -a -o orders-api .
export SW_AGENT_NAME='prod::orders-go'
export SW_AGENT_REPORTER_GRPC_BACKEND_SERVICE='127.0.0.1:11800'
./orders-api

编译工具版本必须与模块版本一致。-a 用于重新构建包,使编译注入生效;多 main 包项目应指定实际构建路径。Go 的后端变量是 SW_AGENT_REPORTER_GRPC_BACKEND_SERVICE,不能直接复制 Java 的后端环境变量。

7. OpenResty、网关与上下文传播

7.1 OpenResty Lua Agent

优先使用已集成 LuaJIT、常用 Lua 库的 OpenResty,避免把旧版 Lua、CJSON 和 Nginx 的手工编译日志直接拼成部署步骤。下面基于 skywalking-nginx-lua 1.0.1 的官方 API,假定完整库位于 /opt/skywalking-nginx-lua/lib,所需 Lua 依赖已安装,OAP 的 HTTP 上报接口可达。

在 nginx.conf 中配置:

events {
    worker_connections 1024;
}

http {
    lua_package_path "/opt/skywalking-nginx-lua/lib/?.lua;;";
    lua_shared_dict tracing_buffer 20m;

    init_worker_by_lua_block {
        local buffer = ngx.shared.tracing_buffer
        buffer:set("serviceName", "prod::edge-gateway")
        buffer:set("serviceInstanceName", "edge-gateway-01")
        buffer:set("includeHostInEntrySpan", false)
        require("skywalking.util").set_randomseed()
        require("skywalking.client"):startBackendTimer("http://127.0.0.1:12800")
        skywalking_tracer = require("skywalking.tracer")
    }

    upstream orders_backend {
        server 127.0.0.1:18081;
    }

    server {
        listen 18080;

        location / {
            rewrite_by_lua_block {
                skywalking_tracer:start("orders-api")
            }
            proxy_pass http://orders_backend;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            body_filter_by_lua_block {
                if ngx.arg[2] then
                    skywalking_tracer:finish()
                end
            }
            log_by_lua_block {
                skywalking_tracer:prepareForReport()
            }
        }
    }
}

OpenResty 和 OAP 不在同一主机或容器时,替换对应地址。网关实例名按部署副本区分,多个 worker 属于同一个网关实例。上游 18081 需要运行已接入 Agent 的实际业务服务,不能使用 Mock OAP 接口冒充采集成功。

openresty -t
openresty -s reload
curl -fsS http://127.0.0.1:18080/orders

module 'tablepool' not found、cjson.safe not found 属于 Lua 依赖或路径问题,先检查 OpenResty 的库路径和该 Agent 的依赖说明,不要随意复制不同版本的 .so。APISIX、Kong 等网关优先使用各自官方 SkyWalking 插件。

Nginx 性能指标与请求 Trace 是不同功能。只需要请求量、连接数和延迟时,可以使用 nginx-lua-prometheus → OpenTelemetry Collector → OAP,并配置对应 Nginx MAL 规则;仅启用 Exporter 不会生成跨服务 Trace。

7.2 跨进程、异步与浏览器

SkyWalking 原生 HTTP 追踪使用 sw8 等上下文头,不能把它当作普通请求 ID 自行拼接。代理若使用白名单清理请求头,需要保留对应追踪头;MQ 的 Producer/Consumer 插件需要支持当前客户端版本和消息属性传播。

自建线程池、回调或异步任务发生断链时,核对 Agent 插件是否覆盖执行模型;必要时使用 Toolkit 的上下文捕获和继续机制,不能只把 Trace ID 放进 ThreadLocal 或 MDC 就认为建立了父子关系。

浏览器观测通过 Browser Agent 收集页面性能和 JavaScript 错误。前后端串联还涉及被追踪域名、HTTP 请求头、CORS 允许头和后端 Agent 支持。生产通常通过网关仅开放必要采集路径,不能为了浏览器上报就把整个 OAP 12800 暴露公网。不要在页面中写 Agent Token 或管理凭据。

8. 日志与 Trace 关联

Java Logback 示例使用与 Agent 配套的 Toolkit。Maven 配置:

<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-logback-1.x</artifactId>
    <version>9.4.0</version>
</dependency>

logback-spring.xml 示例:

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} - %msg%n</Pattern>
            </layout>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

%tid 依赖上述 Layout,不能直接放进任意默认编码器后就期待自动解析。未接入 Agent 或当前线程没有追踪上下文时,Trace ID 可能是 N/A。

把标准输出交给 Alloy、Fluent Bit 等采集器时,需要解析并保留 Trace ID 字段。日志采集与 Trace 上报是两条管道,输出 Trace ID 不会自动把日志发到 OAP;如需 OAP 原生日志查询,需要另行配置日志接收、解析与字段映射,或者使用 Toolkit 的 gRPC 日志 Appender。

SQL、URL、请求体和异常信息可能包含敏感数据。按需采集并脱敏,避免记录密码、Authorization、Cookie、完整用户资料和大体积报文。

9. OpenTelemetry 接入边界

OAP 10.4.0 可以接收 OTLP Trace、Metrics 和 Logs,但不同信号有不同分析规则。OTLP Trace 会转换成 Zipkin Trace,不能直接等同于 SkyWalking 原生 Agent Trace,也不会自动获得 Java Agent 的全部框架插件和原生拓扑分析能力。

在现有 Compose 中为 OAP 增加以下环境变量,启用 Trace 接收和 Zipkin 查询;本例不使用 Kafka:

environment:
  SW_OTEL_RECEIVER: default
  SW_OTEL_RECEIVER_ENABLED_HANDLERS: "otlp-traces,otlp-metrics,otlp-logs"
  SW_RECEIVER_ZIPKIN: default
  SW_ZIPKIN_KAFKA_COLLECTOR_ENABLED: "false"
  SW_QUERY_ZIPKIN: default

UI 增加:

environment:
  SW_ZIPKIN_ADDRESS: http://oap:9412

这些片段应合并到原有 environment,不能替换掉存储配置或 SW_OAP_ADDRESS。修改环境变量后执行 docker compose up -d 重新创建容器。

OTLP 客户端或 Collector 使用明确的 OTLP/gRPC 协议连接 oap:11800,不要默认向 12800/v1/traces 发送 OTLP/HTTP。资源属性至少设置 service.name,并规划环境与实例标识。Trace 使用 UI 的 /zipkin Lens 页面查询。

OTLP 指标需要匹配并启用对应 MAL/OTel 规则,例如 Nginx、OAP 自监控或数据库指标;任意自定义指标即使成功上传,也不一定自动变成可查询的内置仪表盘。已有 OTel Java Agent 的应用不要直接叠加 SkyWalking Java Agent,先评估重复埋点、上下文协议及性能影响。

10. 采样与数据保留

10.1 Agent 采样与 OAP 采样

配置位置示例含义
Java AgentSW_AGENT_SAMPLE=100每个 Agent 每 3 秒的采样数量限制,不是 100%
Java AgentSW_AGENT_SAMPLE=-1关闭该数量限制,不是关闭 Agent
OAPrate: 1000服务端采样率 10%,精度为万分之一
OAPduration: 2000强制保留超过 2000 ms 的慢 Segment

OAP 服务端采样是在接收与指标分析之后减少 Trace 持久化,服务、实例、端点及拓扑指标仍按收到的数据分析;它不会减少 Agent 到 OAP 的上报带宽。Agent 侧已经丢弃的数据,OAP 无法恢复。

/data/skywalking/config/trace-sampling-policy-settings.yml 示例:

default:
  rate: 1000
  duration: 2000
services:
  - name: "prod::payment-api"
    rate: 10000
    duration: 1000

OAP 默认 SW_FORCE_SAMPLE_ERROR_SEGMENT=true,可强制保留错误 Segment。强制保留错误或慢 Segment 不保证整个 Trace 的其他 Segment 都已保存;当故障导致大量慢请求时,实际保存比例可能显著高于基础采样率。

所有 OAP 节点应使用一致策略,避免同一 Trace 的片段因不同采样配置而缺失。静态配置修改后重启 OAP;需要不停机调整时使用该版本支持的动态配置机制。

10.2 TTL 与容量估算

本篇 Elasticsearch 示例使用:

environment:
  SW_CORE_RECORD_DATA_TTL: "3"
  SW_CORE_METRICS_DATA_TTL: "7"

单位是天。记录数据包括 Trace、日志、告警和慢 SQL 等;指标与元数据使用指标 TTL。BanyanDB 有自己的 TTL 配置,不能直接套用这两个 Core TTL 参数。

估算 Trace 存储时至少考虑:

每日 Trace 原始数据量
≈ 每秒完成的请求数 × 86400 × 实际采样率 × 每条 Trace 平均字节数

所需磁盘
≈ 每日索引实际增长量 × 保留天数 × (1 + 副本数) + 索引/合并余量

使用 ES 实际索引增长量评估磁盘更可靠;不要把序列化后的 Trace 大小直接当成磁盘占用。日志、指标、管理数据、分片开销和错误强制采样需要另外计入。监控磁盘水位、分片数量、堆使用率、GC、写入拒绝和查询延迟。

11. 告警规则与钉钉通知

11.1 指标含义

指标含义
service_resp_time服务响应时间,单位 ms
service_cpm每分钟调用次数,不是每秒请求数
service_sla成功率的内部万分比数值,10000 表示 100%
service_percentile服务响应时间分位值,如 P95/P99
endpoint_resp_time端点响应时间,单位 ms

成功率显示为百分比时需注意单位,告警中可使用 service_sla / 100 转换为百分数。错误判断受插件及 Segment 状态分析策略影响,不应只根据业务返回 HTTP 200 就推断一定成功。

11.2 alarm-settings.yml

将下面配置保存到 /data/skywalking/config/alarm-settings.yml。它会覆盖发行版自带规则;钉钉 URL 与签名密钥通过密钥管理系统注入部署文件,下面只使用占位值。

rules:
  service_latency_rule:
    expression: sum(service_resp_time > 1000) >= 3
    period: 10
    silence-period: 10
    message: 'Service {name}: average response time exceeded 1000 ms in at least 3 minute buckets during the last 10 minutes'
    tags:
      level: WARNING
    hooks:
      - dingtalk.ops

  service_success_rate_rule:
    expression: sum((service_sla / 100) < 99) >= 3
    period: 10
    silence-period: 10
    message: 'Service {name}: success rate below 99% in at least 3 minute buckets during the last 10 minutes'
    tags:
      level: CRITICAL
    hooks:
      - dingtalk.ops

hooks:
  dingtalk:
    ops:
      text-template: |-
        {"msgtype":"text","text":{"content":"SkyWalking Alarm: %s"}}
      webhooks:
        - url: "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
          secret: "YOUR_SIGNING_SECRET"

规则 ID 以 _rule 结尾。period 是分钟窗口,sum(... ) >= 3 表示窗口内至少 3 个分钟数据点满足条件,不表示“3 次请求”或“连续 3 分钟”。silence-period 用于抑制重复通知。

表达式需要返回单值布尔结果,不能直接写 service_resp_time > 1000 就假定规则有效。服务级规则和端点级规则应分开;include-names 筛选的是对应实体名,服务分组前缀也需要匹配。

cd /data/skywalking
docker compose restart oap
docker compose logs --tail=100 oap

先确认 UI 中指标存在,再制造可控的慢请求或错误请求观察完整窗口。钉钉机器人还需满足自身的签名、关键词或来源限制。内置 hooks.dingtalk 可直接发送通知,不需要额外编译旧版 Java 转发程序。

自建 Webhook 时,按 SkyWalking 的告警 JSON 格式实现接收和转换;Alertmanager 的 API 与 SkyWalking Webhook 结构不同,不能直接把 URL 指向 Alertmanager 后就认为协议兼容。

12. 自监控与性能剖析

OAP 启用 SW_TELEMETRY=prometheus 后提供 1234/metrics。Prometheus 与 OAP 位于同一 Docker 网络时,可增加:

scrape_configs:
  - job_name: skywalking-oap
    scrape_interval: 15s
    static_configs:
      - targets: ["oap:1234"]

Prometheus 在宿主机运行时可使用 127.0.0.1:1234,远程采集则使用受控内网地址。优先关注 OAP 的 JVM 堆与 GC、接收/分析队列、存储写入失败、磁盘水位、查询延迟及 Agent 的上报异常。仅有 UI 仪表盘不能代替对 OAP 和存储自身的监控。

Trace 已定位到某个应用,但耗时集中在内部代码时,可以进一步创建有时间限制的 Profiling 任务,限定服务、实例和端点,再观察调用栈。Java Agent 的普通追踪剖析、基于 async-profiler 的剖析和 eBPF/Rover 功能有不同的运行时及权限要求,应按所用版本单独配置。先在低风险实例验证,控制采集时长与并发,不长期对全部实例开启高频剖析。

13. 生产部署、备份与升级

13.1 网络、认证与 TLS

通信链路需要的措施
浏览器 → UIHTTPS、统一身份认证或访问控制
UI → OAP 查询管理网络、来源限制,保护 12800
Agent → OAP内网访问控制,按需启用 TLS/mTLS 和 Agent Token
OAP → ElasticsearchTLS、证书校验、最小必要账户权限

Agent Token 只用于相应的采集认证,不会给 UI 或全部 HTTP 查询接口自动增加登录认证。

OAP 与 Java Agent 共享 Token 的配置变量分别是:

OAP:        SW_AUTHENTICATION
Java Agent: SW_AGENT_AUTHENTICATION

Token 从 Secret 或部署系统注入,两端一致。跨不可信网络时同时启用 TLS,Token 本身不会加密传输。

Elasticsearch HTTPS 连接的 OAP 配置变量:

SW_STORAGE_ES_CLUSTER_NODES=es-01.internal:9200,es-02.internal:9200
SW_STORAGE_ES_HTTP_PROTOCOL=https
SW_ES_USER=skywalking
SW_ES_PASSWORD=<由密钥管理系统注入>
SW_STORAGE_ES_SSL_JKS_PATH=/skywalking/certs/es-truststore.jks
SW_STORAGE_ES_SSL_JKS_PASS=<由密钥管理系统注入>

将受信 CA 导入对应 Truststore,并挂载到 OAP。不要把 curl -k 或禁用证书验证作为长期方案。

13.2 多节点与高可用

生产 OAP 可部署多个节点,使用该版本支持的 Kubernetes、ZooKeeper、Consul 等集群发现方式,配置一致的存储、命名空间和采样策略。多台独立的 standalone OAP 放到负载均衡后,不等同于正确的 OAP 集群。

Agent 上报链路需要支持 gRPC/HTTP2,负载均衡器的空闲超时也需要匹配长连接。扩容后确认新节点被发现并接收流量,再根据接收、聚合和存储瓶颈扩容,不能只增加 UI 副本。

13.3 备份与升级

  • 备份 Compose、OAP 覆盖配置、告警规则、镜像版本或摘要以及管理仪表盘。
  • Elasticsearch 使用 Snapshot Repository 备份到独立存储;运行中复制数据目录不能替代一致性快照。
  • 升级前阅读发行说明、存储迁移与 Agent 兼容说明,在测试环境回放典型请求。
  • 灰度验证注册、Trace 串联、日志关联、告警与查询,再逐步切换实例。
  • 存储格式或索引模板已变化时,不能假定降级镜像即可回滚;需要事先验证恢复路径。

停止单机实验环境使用 docker compose down,配置和绑定挂载的 ES 数据仍保留。清理历史记录优先使用 TTL,不要为了修复连接故障直接删除存储目录。

14. 排障步骤

现象排查重点
UI 空白、502 或查询失败UI 日志、SW_OAP_ADDRESS、12800、GraphQL 正文、网关超时
没有服务JVM 是否实际加载 Agent、Agent 目录与日志权限、服务名、DNS、11800、认证及 TLS
有服务但没有 Trace是否产生真实请求、查询时间范围、插件支持、采样策略、忽略规则、写入异常
Trace 跨服务断开各跳 Agent、代理是否保留追踪头、MQ 属性、自建线程池上下文、不同协议之间的传播
UNAVAILABLE 或连接重试地址、端口、DNS、Service Endpoints、NetworkPolicy、gRPC 代理与证书
PERMISSION_DENIEDAgent 与 OAP Token 是否一致、采集认证配置是否实际生效
UNIMPLEMENTEDAgent 使用的协议或功能是否超出 OAP 支持范围、是否连错服务
OAP 健康接口 503模块健康详情、ES 连通性、认证、磁盘水位、索引写入与 OAP 内存
ES 为 yellow检查是否仅为单节点无法分配副本,不要把 yellow 一概当作写入失败
ES 出现 read_only_allow_delete先解决磁盘水位,再确认相应版本的只读块恢复机制
日志出现 N/A当前线程是否有 Trace、Toolkit 与 Layout 是否加载、异步上下文是否传播
告警不发送指标名与单位、MQE 表达式、分钟窗口、静默期、Hook 绑定、Webhook 网络与响应
服务或端点数量持续膨胀服务名是否包含随机值、URL 是否模板化、标签是否混入用户 ID 或订单号

主机 Compose 排查:

cd /data/skywalking
docker compose ps
docker compose logs --since=10m --tail=200 oap
curl -fsS http://127.0.0.1:12800/healthcheck
ss -lnt | grep -E ':(11800|12800|8080|1234)\b'
docker compose exec -T elasticsearch \
  curl -fsS 'http://localhost:9200/_cluster/health?pretty'
docker compose exec -T elasticsearch \
  curl -fsS 'http://localhost:9200/_cat/allocation?v'

端口监听只证明进程打开了端口。排障顺序应是:Agent 已加载 → 地址和协议正确 → 认证及网络通过 → OAP 模块健康 → 存储可写 → 产生业务请求 → UI 按正确时间、服务和实例查询。跨主机时间不一致会影响时间范围和链路耗时分析,统一使用 NTP/chrony 同步。

最终验收至少包含一个实际业务入口、一次下游调用和一次可控错误:服务及实例出现,Trace ID 能跨服务关联,错误与延迟指标符合请求结果,日志能检索到相同 Trace ID,告警能够送达。

15. 官方参考

评论