
👋 大家好,欢迎来到我的技术博客!
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕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 参数(可选))
- [📄 修改 `config/application.yml`](#📄 修改
- [▶️ 启动 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注解)
- [✍️ 使用 `@Trace` 注解](#✍️ 使用
- [🎯 高级功能:OpenTelemetry Bridge](#🎯 高级功能:OpenTelemetry Bridge)
-
- [Maven 依赖](#Maven 依赖)
- [初始化 OTel Tracer](#初始化 OTel Tracer)
- 在业务代码中使用
- [📊 数据存储优化:Elasticsearch 索引管理](#📊 数据存储优化:Elasticsearch 索引管理)
-
- [方案一:使用 ILM(Index Lifecycle Management)](#方案一:使用 ILM(Index Lifecycle Management))
- [方案二:使用 Curator 工具定期清理](#方案二:使用 Curator 工具定期清理)
- [🚨 告警配置:让问题主动找你](#🚨 告警配置:让问题主动找你)
-
- [编辑 `config/alarm-settings.yml`](#编辑
config/alarm-settings.yml) - [实现 Webhook 接收器(Java 示例)](#实现 Webhook 接收器(Java 示例))
- [编辑 `config/alarm-settings.yml`](#编辑
- [🔄 性能调优建议](#🔄 性能调优建议)
-
- [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
导入后即可监控:
- 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 节点或分片数
- 调整
bulkActions和flushInterval - 启用采样降低数据量
🌐 多数据中心部署架构
对于大型企业,可能需要跨机房部署 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
📚 学习资源推荐
- Apache SkyWalking 官方文档:https://skywalking.apache.org/docs/
- Elasticsearch 官方指南:https://www.elastic.co/guide/index.html
- OpenTelemetry Java SDK:https://github.com/open-telemetry/opentelemetry-java (注意:此处仅为说明,实际部署请勿直接访问 GitHub)
- SkyWalking 社区 Slack:可通过官网加入讨论组
🎁 结语:构建你的可观测性未来
通过本文,你已经掌握了:
✅ 如何部署高可用的 SkyWalking + Elasticsearch 生产架构
✅ Java 应用无缝接入与自定义埋点
✅ 数据存储生命周期管理
✅ 告警通知与外部系统集成
✅ 性能调优与多数据中心方案
SkyWalking 不仅仅是一个"链路追踪工具",它正在演变为企业级可观测性平台的核心引擎。结合 Logs(日志)、Metrics(指标)、Traces(追踪)三大支柱,你将有能力在复杂分布式系统中快速定位故障、优化性能、提升用户体验。
现在就开始行动吧!让你的系统"看得见、管得住、调得优" 🌟。
📝 作者提示:技术更新快,建议定期查阅官方文档获取最新特性。生产部署前务必进行压测与容量规划。祝你监控无忧,系统稳如泰山!
🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍 点赞 、📌 收藏 、📤 分享 给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨