SkyWalking - 生产级部署:集成 Elasticsearch 作为后端存储

👋 大家好,欢迎来到我的技术博客!

📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。

🎯 本文将围绕SkyWalking 这个话题展开,希望能为你带来一些启发或实用的参考。

🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!


文章目录

  • [🚀 SkyWalking - 生产级部署:集成 Elasticsearch 作为后端存储](#🚀 SkyWalking - 生产级部署:集成 Elasticsearch 作为后端存储)
    • [🔍 为什么选择 Elasticsearch?](#🔍 为什么选择 Elasticsearch?)
      • [✅ 优势一览:](#✅ 优势一览:)
    • [🧩 架构概览:SkyWalking + Elasticsearch](#🧩 架构概览:SkyWalking + Elasticsearch)
    • [🛠️ 第一步:部署 Elasticsearch 集群](#🛠️ 第一步:部署 Elasticsearch 集群)
      • [⚙️ 配置建议(elasticsearch.yml)](#⚙️ 配置建议(elasticsearch.yml))
    • [📦 第二步:下载并配置 SkyWalking OAP Server](#📦 第二步:下载并配置 SkyWalking OAP Server)
      • [📄 修改 `config/application.yml`](#📄 修改 config/application.yml)
      • [⚙️ 调整 JVM 参数(可选)](#⚙️ 调整 JVM 参数(可选))
    • [▶️ 启动 OAP 服务](#▶️ 启动 OAP 服务)
    • [🖥️ 第三步:启动 UI 服务](#🖥️ 第三步:启动 UI 服务)
    • [☕ 第四步:Java 应用接入 SkyWalking Agent](#☕ 第四步:Java 应用接入 SkyWalking Agent)
      • [方法一:命令行挂载 Agent(推荐)](#方法一:命令行挂载 Agent(推荐))
      • [方法二:Spring Boot 配置文件方式(需配合插件)](#方法二:Spring Boot 配置文件方式(需配合插件))
    • [🧪 示例:编写一个被监控的 Java 服务](#🧪 示例:编写一个被监控的 Java 服务)
      • [📄 pom.xml](#📄 pom.xml)
      • [📄 OrderController.java](#📄 OrderController.java)
      • [📄 UserService.java(另一个服务)](#📄 UserService.java(另一个服务))
    • [📈 自定义指标与埋点(Manual Instrumentation)](#📈 自定义指标与埋点(Manual Instrumentation))
      • [✍️ 使用 `@Trace` 注解](#✍️ 使用 @Trace 注解)
    • [🎯 高级功能:OpenTelemetry Bridge](#🎯 高级功能:OpenTelemetry Bridge)
    • [📊 数据存储优化:Elasticsearch 索引管理](#📊 数据存储优化:Elasticsearch 索引管理)
      • [方案一:使用 ILM(Index Lifecycle Management)](#方案一:使用 ILM(Index Lifecycle Management))
      • [方案二:使用 Curator 工具定期清理](#方案二:使用 Curator 工具定期清理)
    • [🚨 告警配置:让问题主动找你](#🚨 告警配置:让问题主动找你)
      • [编辑 `config/alarm-settings.yml`](#编辑 config/alarm-settings.yml)
      • [实现 Webhook 接收器(Java 示例)](#实现 Webhook 接收器(Java 示例))
    • [🔄 性能调优建议](#🔄 性能调优建议)
      • [1. Agent 端采样率控制](#1. Agent 端采样率控制)
      • [2. OAP 批量写入优化](#2. OAP 批量写入优化)
      • [3. 关闭不需要的指标](#3. 关闭不需要的指标)
    • [🧪 监控 SkyWalking 自身](#🧪 监控 SkyWalking 自身)
      • [启用 Prometheus Exporter](#启用 Prometheus Exporter)
      • [导入 Grafana Dashboard](#导入 Grafana Dashboard)
    • [🧭 故障排查常见问题](#🧭 故障排查常见问题)
      • [❌ Agent 数据未上报](#❌ Agent 数据未上报)
      • [❌ UI 无数据 / 图表空白](#❌ UI 无数据 / 图表空白)
      • [❌ ES 写入慢 / OOM](#❌ ES 写入慢 / OOM)
    • [🌐 多数据中心部署架构](#🌐 多数据中心部署架构)
    • [📚 学习资源推荐](#📚 学习资源推荐)
    • [🎁 结语:构建你的可观测性未来](#🎁 结语:构建你的可观测性未来)

🚀 SkyWalking - 生产级部署:集成 Elasticsearch 作为后端存储

在微服务架构和云原生时代,分布式追踪与性能监控已成为保障系统稳定性和可观测性的核心能力。Apache SkyWalking 作为一款开源的 APM(Application Performance Monitoring)系统,凭借其轻量级探针、强大的可视化界面以及灵活的后端存储架构,在国内外企业中获得了广泛采用。而在生产环境中,选择合适的后端存储是确保 SkyWalking 长期稳定运行的关键一步 ------ Elasticsearch 是目前官方推荐且社区最常用的生产级存储方案

本文将从零开始,带你完整搭建一套基于 Elasticsearch 的 SkyWalking 生产环境部署方案,并通过 Java 代码示例展示如何接入应用、定制指标、处理告警等实用技巧。无论你是 DevOps 工程师、SRE 运维人员,还是 Java 后端开发者,都能从中获得可落地的实战经验 💪。


🔍 为什么选择 Elasticsearch?

SkyWalking 支持多种后端存储,包括 H2(仅用于开发)、MySQL、TiDB、InfluxDB、BanyanDB 和 Elasticsearch。但在生产环境中,Elasticsearch 凭借其高性能全文检索、水平扩展能力、成熟生态和社区支持,成为绝大多数企业的首选

✅ 优势一览:

  • 高吞吐写入:适合海量追踪数据持续写入。
  • 快速聚合查询:支持复杂的链路分析、服务拓扑、慢调用筛选。
  • 自动分片与副本:保障数据高可用与容灾。
  • 成熟的运维工具链:Kibana、Curator、ILM 等配套工具完善。
  • 与 SkyWalking 深度集成:官方提供完整的索引模板、生命周期策略支持。

📌 官方文档参考:https://skywalking.apache.org/docs/


🧩 架构概览:SkyWalking + Elasticsearch

在正式动手之前,我们先了解整体架构。一个典型的 SkyWalking 生产部署包含以下组件:
#mermaid-svg-VddlindH1dnRPiiV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VddlindH1dnRPiiV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VddlindH1dnRPiiV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VddlindH1dnRPiiV .error-icon{fill:#552222;}#mermaid-svg-VddlindH1dnRPiiV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VddlindH1dnRPiiV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VddlindH1dnRPiiV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VddlindH1dnRPiiV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VddlindH1dnRPiiV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VddlindH1dnRPiiV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VddlindH1dnRPiiV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VddlindH1dnRPiiV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VddlindH1dnRPiiV .marker.cross{stroke:#333333;}#mermaid-svg-VddlindH1dnRPiiV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VddlindH1dnRPiiV p{margin:0;}#mermaid-svg-VddlindH1dnRPiiV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VddlindH1dnRPiiV .cluster-label text{fill:#333;}#mermaid-svg-VddlindH1dnRPiiV .cluster-label span{color:#333;}#mermaid-svg-VddlindH1dnRPiiV .cluster-label span p{background-color:transparent;}#mermaid-svg-VddlindH1dnRPiiV .label text,#mermaid-svg-VddlindH1dnRPiiV span{fill:#333;color:#333;}#mermaid-svg-VddlindH1dnRPiiV .node rect,#mermaid-svg-VddlindH1dnRPiiV .node circle,#mermaid-svg-VddlindH1dnRPiiV .node ellipse,#mermaid-svg-VddlindH1dnRPiiV .node polygon,#mermaid-svg-VddlindH1dnRPiiV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VddlindH1dnRPiiV .rough-node .label text,#mermaid-svg-VddlindH1dnRPiiV .node .label text,#mermaid-svg-VddlindH1dnRPiiV .image-shape .label,#mermaid-svg-VddlindH1dnRPiiV .icon-shape .label{text-anchor:middle;}#mermaid-svg-VddlindH1dnRPiiV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VddlindH1dnRPiiV .rough-node .label,#mermaid-svg-VddlindH1dnRPiiV .node .label,#mermaid-svg-VddlindH1dnRPiiV .image-shape .label,#mermaid-svg-VddlindH1dnRPiiV .icon-shape .label{text-align:center;}#mermaid-svg-VddlindH1dnRPiiV .node.clickable{cursor:pointer;}#mermaid-svg-VddlindH1dnRPiiV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VddlindH1dnRPiiV .arrowheadPath{fill:#333333;}#mermaid-svg-VddlindH1dnRPiiV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VddlindH1dnRPiiV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VddlindH1dnRPiiV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VddlindH1dnRPiiV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VddlindH1dnRPiiV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VddlindH1dnRPiiV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VddlindH1dnRPiiV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VddlindH1dnRPiiV .cluster text{fill:#333;}#mermaid-svg-VddlindH1dnRPiiV .cluster span{color:#333;}#mermaid-svg-VddlindH1dnRPiiV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VddlindH1dnRPiiV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VddlindH1dnRPiiV rect.text{fill:none;stroke-width:0;}#mermaid-svg-VddlindH1dnRPiiV .icon-shape,#mermaid-svg-VddlindH1dnRPiiV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VddlindH1dnRPiiV .icon-shape p,#mermaid-svg-VddlindH1dnRPiiV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VddlindH1dnRPiiV .icon-shape rect,#mermaid-svg-VddlindH1dnRPiiV .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VddlindH1dnRPiiV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VddlindH1dnRPiiV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VddlindH1dnRPiiV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} OTel/SkyWalking Agent
Data Storage & Query
Optional
Java Application
OAP Server
Elasticsearch Cluster
UI Frontend
Prometheus/Grafana
Alerting System

  • Agent:嵌入在应用 JVM 中,负责采集追踪、指标、日志等数据。
  • OAP Server (Observability Analysis Platform):接收 Agent 数据,进行聚合、分析、持久化到 ES。
  • Elasticsearch:作为核心存储引擎,保存所有原始与聚合数据。
  • UI:前端可视化界面,供用户查看拓扑、链路、指标、告警等。
  • 可选组件:如 Prometheus 推送网关、邮件/Webhook 告警通知等。

🛠️ 第一步:部署 Elasticsearch 集群

虽然单节点 ES 可用于测试,但生产环境建议至少 3 节点集群,保障高可用。

⚙️ 配置建议(elasticsearch.yml)

yaml 复制代码
cluster.name: skywalking-prod
node.name: es-node-1
network.host: 0.0.0.0
discovery.seed_hosts: ["es-node-1", "es-node-2", "es-node-3"]
cluster.initial_master_nodes: ["es-node-1", "es-node-2", "es-node-3"]

# JVM 设置(根据机器内存调整)
-Xms8g
-Xmx8g

# 开启安全认证(生产必需)
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true

🔐 生产环境务必启用 TLS + 用户认证!可参考官方安全指南:https://www.elastic.co/guide/en/elasticsearch/reference/current/security-minimal-setup.html

启动后,验证集群健康状态:

bash 复制代码
curl -u elastic:yourpassword -X GET "localhost:9200/_cluster/health?pretty"

应返回 "status" : "green""yellow"


📦 第二步:下载并配置 SkyWalking OAP Server

前往官网下载最新稳定版(如 v9.4.0):

bash 复制代码
wget https://archive.apache.org/dist/skywalking/9.4.0/apache-skywalking-apm-9.4.0.tar.gz
tar -zxvf apache-skywalking-apm-9.4.0.tar.gz
cd apache-skywalking-apm-bin

📄 修改 config/application.yml

重点配置存储为 elasticsearch:

yaml 复制代码
storage:
  selector: ${SW_STORAGE:elasticsearch}
  elasticsearch:
    namespace: ${SW_NAMESPACE:""}
    clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
    protocol: ${SW_STORAGE_ES_HTTP_PROTOCOL:"http"}
    user: ${SW_ES_USER:elastic}
    password: ${SW_ES_PASSWORD:yourpassword}
    trustStorePath: ${SW_STORAGE_ES_SSL_JKS_PATH:""}
    trustStorePass: ${SW_STORAGE_ES_SSL_JKS_PASS:""}
    indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:1}
    indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:1}
    # 开启滚动索引,避免单索引过大
    dayStep: ${SW_STORAGE_DAY_STEP:1}
    enablePackedDownsampling: ${ENABLE_PACKED_DOWNSAMPLING:true}

⚙️ 调整 JVM 参数(可选)

编辑 bin/oapService.sh,增加堆内存:

bash 复制代码
JAVA_OPTS="$JAVA_OPTS -Xms4g -Xmx4g"

▶️ 启动 OAP 服务

bash 复制代码
./bin/oapService.sh

观察日志 logs/skywalking-oap-server.log,确认无报错且成功连接 ES:

复制代码
Connected to Elasticsearch cluster [skywalking-prod] successfully.

🖥️ 第三步:启动 UI 服务

SkyWalking UI 是独立进程,默认监听 8080 端口。

bash 复制代码
./bin/webappService.sh

访问 http://your-server-ip:8080,即可看到仪表盘界面 👏。


☕ 第四步:Java 应用接入 SkyWalking Agent

这是最关键的一步 ------ 让你的 Java 应用"被监控"。

方法一:命令行挂载 Agent(推荐)

下载 SkyWalking Agent 包(通常在 OAP 同目录的 agent/ 文件夹内),或单独下载。

启动 Java 应用时添加参数:

bash 复制代码
java -javaagent:/path/to/skywalking-agent/skywalking-agent.jar \
     -Dskywalking.agent.service_name=your-service-name \
     -Dskywalking.collector.backend_service=your-oap-server:11800 \
     -jar your-application.jar

方法二:Spring Boot 配置文件方式(需配合插件)

如果你使用 Spring Boot,可通过环境变量注入:

yaml 复制代码
# application.yml
skywalking:
  agent:
    service_name: order-service
    collector:
      backend_service: 192.168.1.100:11800

并在启动脚本中依然保留 -javaagent 参数。


🧪 示例:编写一个被监控的 Java 服务

下面是一个简单的 Spring Boot Web 服务,我们将演示它如何被 SkyWalking 自动追踪。

📄 pom.xml

xml 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

📄 OrderController.java

java 复制代码
@RestController
@RequestMapping("/order")
public class OrderController {

    private final RestTemplate restTemplate;

    public OrderController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @GetMapping("/create/{userId}")
    public String createOrder(@PathVariable String userId) {
        // 模拟调用用户服务
        String userInfo = restTemplate.getForObject(
            "http://localhost:8082/user/info/" + userId, String.class);

        // 模拟数据库操作耗时
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        return "Order created for user: " + userInfo;
    }
}

📄 UserService.java(另一个服务)

java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/info/{id}")
    public String getUserInfo(@PathVariable String id) {
        try {
            Thread.sleep(150); // 模拟查询延迟
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return "User-" + id + "-Profile";
    }
}

分别启动这两个服务,并挂载 SkyWalking Agent:

bash 复制代码
# 启动用户服务
java -javaagent:./agent/skywalking-agent.jar \
     -Dskywalking.agent.service_name=user-service \
     -Dskywalking.collector.backend_service=192.168.1.100:11800 \
     -jar user-service.jar --server.port=8082

# 启动订单服务
java -javaagent:./agent/skywalking-agent.jar \
     -Dskywalking.agent.service_name=order-service \
     -Dskywalking.collector.backend_service=192.168.1.100:11800 \
     -jar order-service.jar --server.port=8081

访问 http://localhost:8081/order/create/1001,然后打开 SkyWalking UI,你将看到:

  • 自动生成的服务拓扑图 🗺️
  • 跨服务的完整调用链路 🔄
  • 各接口响应时间、吞吐量、错误率等指标 📊

📈 自定义指标与埋点(Manual Instrumentation)

虽然 SkyWalking 提供了大量自动埋点(如 Spring MVC、Feign、JDBC、Redis 等),但在某些业务场景下,我们需要手动记录关键方法耗时或自定义标签。

✍️ 使用 @Trace 注解

java 复制代码
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.apache.skywalking.apm.toolkit.trace.Tag;

@Service
public class PaymentService {

    @Trace
    @Tag(key = "payment.amount", value = "arg[0]")
    @Tag(key = "payment.currency", value = "arg[1]")
    public boolean processPayment(double amount, String currency) {
        try {
            Thread.sleep(300); // 模拟支付网关调用
            return Math.random() > 0.1; // 90% 成功率
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }
}

该方法将出现在 SkyWalking 的"追踪"页面,并携带自定义标签,便于筛选和聚合。


🎯 高级功能:OpenTelemetry Bridge

SkyWalking 从 8.x 版本开始支持 OpenTelemetry 协议,这意味着你可以使用 OTel SDK 发送数据到 SkyWalking OAP,无需绑定 SkyWalking Agent。

Maven 依赖

xml 复制代码
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-api</artifactId>
    <version>1.27.0</version>
</dependency>
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk</artifactId>
    <version>1.27.0</version>
</dependency>
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-otlp</artifactId>
    <version>1.27.0</version>
</dependency>

初始化 OTel Tracer

java 复制代码
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;

public class OtelConfig {

    public static Tracer initTracer() {
        OtlpGrpcSpanExporter exporter = OtlpGrpcSpanExporter.builder()
            .setEndpoint("http://your-oap-server:11800") // SkyWalking OAP OTLP 端口
            .build();

        SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
            .addSpanProcessor(BatchSpanProcessor.builder(exporter).build())
            .build();

        OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
            .setTracerProvider(tracerProvider)
            .buildAndRegisterGlobal();

        return openTelemetry.getTracer("my-app-tracer");
    }
}

在业务代码中使用

java 复制代码
@RestController
public class InventoryController {

    private final Tracer tracer = OtelConfig.initTracer();

    @GetMapping("/deduct/{skuId}/{qty}")
    public String deductInventory(@PathVariable String skuId, @PathVariable int qty) {
        var span = tracer.spanBuilder("deductInventory").startSpan();
        try (var scope = span.makeCurrent()) {
            span.setAttribute("sku.id", skuId);
            span.setAttribute("quantity", qty);

            // 业务逻辑
            simulateStockDeduction(skuId, qty);

            span.addEvent("Inventory deducted successfully");
            return "Success";
        } catch (Exception e) {
            span.recordException(e);
            throw e;
        } finally {
            span.end();
        }
    }

    private void simulateStockDeduction(String skuId, int qty) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

这样,即使不使用 SkyWalking Agent,也能将追踪数据上报至 SkyWalking 平台,并享受相同的可视化能力!

📘 OpenTelemetry 官方文档:https://opentelemetry.io/docs/


📊 数据存储优化:Elasticsearch 索引管理

随着数据增长,ES 索引会迅速膨胀。SkyWalking 默认按天创建索引(如 sw_service_traffic-20240601),但若不加以管理,可能导致磁盘爆满。

方案一:使用 ILM(Index Lifecycle Management)

在 Kibana 中创建策略:

json 复制代码
PUT _ilm/policy/skywalking_policy
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_size": "50gb",
            "max_age": "1d"
          },
          "set_priority": {
            "priority": 100
          }
        }
      },
      "delete": {
        "min_age": "30d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

然后为 SkyWalking 索引模板绑定该策略:

json 复制代码
PUT _index_template/skywalking_template
{
  "index_patterns": ["sw_*"],
  "template": {
    "settings": {
      "index.lifecycle.name": "skywalking_policy",
      "index.lifecycle.rollover_alias": "skywalking-data"
    }
  }
}

方案二:使用 Curator 工具定期清理

安装 curator:

bash 复制代码
pip install elasticsearch-curator

编写配置文件 curator.yml

yaml 复制代码
client:
  hosts:
    - localhost
  port: 9200
  url_prefix:
  use_ssl: False
  timeout: 30

编写动作文件 actions.yml

yaml 复制代码
actions:
  1:
    action: delete_indices
    description: "Delete indices older than 30 days"
    options:
      ignore_empty_list: True
      disable_action: False
    filters:
    - filtertype: pattern
      kind: prefix
      value: sw_
    - filtertype: age
      source: name
      direction: older
      timestring: '%Y%m%d'
      unit: days
      unit_count: 30

定时执行:

bash 复制代码
curator --config curator.yml actions.yml

🚨 告警配置:让问题主动找你

SkyWalking 内置告警引擎,支持基于规则触发通知。

编辑 config/alarm-settings.yml

yaml 复制代码
rules:
  service_resp_time_rule:
    metrics-name: service_resp_time
    op: ">"
    threshold: 1000
    period: 10
    count: 3
    silence-period: 5
    message: "服务 {name} 响应时间超过 1s"

  service_sla_rule:
    metrics-name: service_sla
    op: "<"
    threshold: 99.9
    period: 10
    count: 2
    silence-period: 10
    message: "服务 {name} SLA 低于 99.9%"

webhooks:
  - http://alert-manager.company.com/skywalking-hook

实现 Webhook 接收器(Java 示例)

java 复制代码
@RestController
@RequestMapping("/skywalking-hook")
public class AlertWebhookController {

    private static final Logger logger = LoggerFactory.getLogger(AlertWebhookController.class);

    @PostMapping
    public ResponseEntity<String> handleAlert(@RequestBody List<AlertMessage> alerts) {
        for (AlertMessage alert : alerts) {
            logger.warn("🚨 SkyWalking Alert: {}", alert.getMessage());

            // 发送邮件、企业微信、钉钉等
            sendDingTalkNotification(alert);
        }
        return ResponseEntity.ok("Received");
    }

    private void sendDingTalkNotification(AlertMessage alert) {
        String webhookUrl = "https://oapi.dingtalk.com/robot/send?access_token=xxx";

        String payload = String.format("""
            {
              "msgtype": "text",
              "text": {
                "content": "【SkyWalking告警】\\n%s\\n时间:%s"
              }
            }
            """, alert.getMessage(), new Date());

        try {
            HttpClient.newHttpClient().send(
                HttpRequest.newBuilder()
                    .uri(URI.create(webhookUrl))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(payload))
                    .build(),
                HttpResponse.BodyHandlers.ofString()
            );
        } catch (Exception e) {
            logger.error("发送钉钉通知失败", e);
        }
    }
}

// DTO 类
class AlertMessage {
    private String name;
    private String message;
    // getter/setter 省略
}

🔄 性能调优建议

1. Agent 端采样率控制

在高流量场景下,全量采集可能造成性能压力。可通过 agent.sample_n_per_3_secs 控制采样:

bash 复制代码
-Dskywalking.agent.sample_n_per_3_secs=5000

表示每 3 秒最多采集 5000 条 Trace。

2. OAP 批量写入优化

application.yml 中调整:

yaml 复制代码
storage:
  elasticsearch:
    bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:5000}
    flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:10}
    concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:2}

3. 关闭不需要的指标

例如,若不关心 JVM 指标,可在 application.yml 中关闭:

yaml 复制代码
core:
  default:
    restHeartBeatSwitch: false
    oalEngine:
      enable: true
      watchFiles: false

🧪 监控 SkyWalking 自身

"谁来监控监控系统?" ------ 答案是:Prometheus + Grafana。

SkyWalking OAP 支持暴露 Prometheus 指标:

启用 Prometheus Exporter

config/application.yml 中:

yaml 复制代码
prometheus-fetcher:
  selector: ${SW_PROMETHEUS_FETCHER:default}
  default:
    enabled: ${SW_PROMETHEUS_FETCHER_ENABLED:true}

访问 http://oap-server:1234/metrics 可看到指标输出。

导入 Grafana Dashboard

Grafana 官方有 SkyWalking 专属看板:

📊 Dashboard ID: 15033

地址:https://grafana.com/grafana/dashboards/15033

导入后即可监控:

  • OAP JVM 内存、GC
  • ES 写入延迟、队列积压
  • Agent 连接数、采样率
  • 告警触发次数

🧭 故障排查常见问题

❌ Agent 数据未上报

  • 检查 -javaagent 路径是否正确
  • 检查 backend_service 是否可达(telnet 11800)
  • 查看 logs/skywalking-api.log 是否有异常

❌ UI 无数据 / 图表空白

  • 确认 OAP 是否连接 ES 成功
  • 检查 ES 索引是否创建(GET _cat/indices/sw_*
  • 查看浏览器 Network 是否 200,排除跨域问题

❌ ES 写入慢 / OOM

  • 增加 ES 节点或分片数
  • 调整 bulkActionsflushInterval
  • 启用采样降低数据量

🌐 多数据中心部署架构

对于大型企业,可能需要跨机房部署 SkyWalking。典型架构如下:
#mermaid-svg-mF2UusaqwCb7qBTz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mF2UusaqwCb7qBTz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mF2UusaqwCb7qBTz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mF2UusaqwCb7qBTz .error-icon{fill:#552222;}#mermaid-svg-mF2UusaqwCb7qBTz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mF2UusaqwCb7qBTz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mF2UusaqwCb7qBTz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mF2UusaqwCb7qBTz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mF2UusaqwCb7qBTz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mF2UusaqwCb7qBTz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mF2UusaqwCb7qBTz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mF2UusaqwCb7qBTz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mF2UusaqwCb7qBTz .marker.cross{stroke:#333333;}#mermaid-svg-mF2UusaqwCb7qBTz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mF2UusaqwCb7qBTz p{margin:0;}#mermaid-svg-mF2UusaqwCb7qBTz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mF2UusaqwCb7qBTz .cluster-label text{fill:#333;}#mermaid-svg-mF2UusaqwCb7qBTz .cluster-label span{color:#333;}#mermaid-svg-mF2UusaqwCb7qBTz .cluster-label span p{background-color:transparent;}#mermaid-svg-mF2UusaqwCb7qBTz .label text,#mermaid-svg-mF2UusaqwCb7qBTz span{fill:#333;color:#333;}#mermaid-svg-mF2UusaqwCb7qBTz .node rect,#mermaid-svg-mF2UusaqwCb7qBTz .node circle,#mermaid-svg-mF2UusaqwCb7qBTz .node ellipse,#mermaid-svg-mF2UusaqwCb7qBTz .node polygon,#mermaid-svg-mF2UusaqwCb7qBTz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mF2UusaqwCb7qBTz .rough-node .label text,#mermaid-svg-mF2UusaqwCb7qBTz .node .label text,#mermaid-svg-mF2UusaqwCb7qBTz .image-shape .label,#mermaid-svg-mF2UusaqwCb7qBTz .icon-shape .label{text-anchor:middle;}#mermaid-svg-mF2UusaqwCb7qBTz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mF2UusaqwCb7qBTz .rough-node .label,#mermaid-svg-mF2UusaqwCb7qBTz .node .label,#mermaid-svg-mF2UusaqwCb7qBTz .image-shape .label,#mermaid-svg-mF2UusaqwCb7qBTz .icon-shape .label{text-align:center;}#mermaid-svg-mF2UusaqwCb7qBTz .node.clickable{cursor:pointer;}#mermaid-svg-mF2UusaqwCb7qBTz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mF2UusaqwCb7qBTz .arrowheadPath{fill:#333333;}#mermaid-svg-mF2UusaqwCb7qBTz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mF2UusaqwCb7qBTz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mF2UusaqwCb7qBTz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mF2UusaqwCb7qBTz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mF2UusaqwCb7qBTz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mF2UusaqwCb7qBTz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mF2UusaqwCb7qBTz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mF2UusaqwCb7qBTz .cluster text{fill:#333;}#mermaid-svg-mF2UusaqwCb7qBTz .cluster span{color:#333;}#mermaid-svg-mF2UusaqwCb7qBTz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mF2UusaqwCb7qBTz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mF2UusaqwCb7qBTz rect.text{fill:none;stroke-width:0;}#mermaid-svg-mF2UusaqwCb7qBTz .icon-shape,#mermaid-svg-mF2UusaqwCb7qBTz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mF2UusaqwCb7qBTz .icon-shape p,#mermaid-svg-mF2UusaqwCb7qBTz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mF2UusaqwCb7qBTz .icon-shape rect,#mermaid-svg-mF2UusaqwCb7qBTz .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mF2UusaqwCb7qBTz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mF2UusaqwCb7qBTz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mF2UusaqwCb7qBTz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} DC2
DC1
专线/VPN
App-A
OAP1
App-B
Elasticsearch Cluster
UI1
App-C
OAP2
App-D
Elasticsearch Cluster
UI2
Global UI

每个数据中心部署独立的 OAP + ES,前端 UI 可聚合多个 OAP 数据源:

yaml 复制代码
# webapp.yml
collector:
  servers: 192.168.1.100:12800,192.168.2.100:12800

📚 学习资源推荐


🎁 结语:构建你的可观测性未来

通过本文,你已经掌握了:

✅ 如何部署高可用的 SkyWalking + Elasticsearch 生产架构

✅ Java 应用无缝接入与自定义埋点

✅ 数据存储生命周期管理

✅ 告警通知与外部系统集成

✅ 性能调优与多数据中心方案

SkyWalking 不仅仅是一个"链路追踪工具",它正在演变为企业级可观测性平台的核心引擎。结合 Logs(日志)、Metrics(指标)、Traces(追踪)三大支柱,你将有能力在复杂分布式系统中快速定位故障、优化性能、提升用户体验。

现在就开始行动吧!让你的系统"看得见、管得住、调得优" 🌟。


📝 作者提示:技术更新快,建议定期查阅官方文档获取最新特性。生产部署前务必进行压测与容量规划。祝你监控无忧,系统稳如泰山!


🙌 感谢你读到这里!

🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。

💡 如果本文对你有帮助,不妨 👍 点赞 、📌 收藏 、📤 分享 给更多需要的朋友!

💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿

🔔 关注我,不错过下一篇干货!我们下期再见!✨

相关推荐
醉颜凉20 分钟前
Elasticsearch服务器部署:从零到一完整启动+配置教程
大数据·服务器·elasticsearch
涛思数据(TDengine)1 小时前
从_找根因_到_搭系统_:工业 AI 实战直播(十、十一期)
大数据·数据库·人工智能·时序数据库·tdengine
GEO_youxuan1 小时前
2026年港口充电堆厂家推荐:功率与防护解析
大数据
Capricorn19881 小时前
科研引用无法溯源怎么排查?知芽 Notebook Skill 技术机制拆解
大数据·论文阅读·人工智能·笔记·论文笔记
Acrellea1 小时前
当机柜功率冲向 50kW,配电运维如何跟上算力的进化速度?
大数据·运维
2601_955759881 小时前
Claude API 容量规划与业务增长评估
大数据·人工智能
Capricorn19881 小时前
Agent 记忆层接入后引用仍不可信?知芽 Notebook Skill 排障指南
大数据·论文阅读·人工智能·笔记·架构
A hao1 小时前
户外LED广告牌需要什么防护等级IP级别?
大数据·网络·图像处理·人工智能·网络协议·tcp/ip·广告
l1258652 小时前
# LangGraph 核心架构入门:State、Node、Edge 与 Reducer 的工程理解
大数据·人工智能·python·架构·langchain·edge