SkyWalking 每日写入 ES 数据量过大排查与降采样
记录时间:2026-08-13
环境:dyck 生产信创环境(RKE + ARM64)| SkyWalking 9.3.0 | Elasticsearch 7.17.28(3 节点)
一、问题现象
最近发现 dyck 生产的 SkyWalking 往 ES 写数据特别猛,sw_segment-* 索引三天的数据长这样:
| 索引 | 文档数 | 存储大小 |
|---|---|---|
| sw_segment-20260812 | 6.63 亿 | 373.2 GB |
| sw_segment-20260813 | 6.37 亿 | 367.5 GB |
| sw_segment-20260814 | 4.09 亿 | 243.4 GB |
按 ES _cat/indices 的列序看,这些索引 pri=5 主分片、rep=0 零副本,每天稳定灌进去 4~6.6 亿条 segment,三天加起来快 1TB 了,ES 压力不小。
二、排查过程
2.1 先看 OAP 有没有配数据保留
先翻 prod-xc 的 OAP 部署文件,发现 env 里只有存储地址和账号密码,一个 TTL 环境变量都没有。SkyWalking 9.3.0 默认 recordDataTTL=3 天、metricsDataTTL=7 天,所以 ES 里同时留着 3 天的 segment 索引。这不是「没清理」,而是每天真实写入就有 ~300GB,攒 3 天就堆到 1TB。
2.2 翻 chart 模板看采样
翻 yw-helm-charts/gzeport-jar 的 templates/deployment.yaml,找到采样那个环境变量:
- name: SW_AGENT_SAMPLE_N_PER_3_SECS
value: {{ .Values.skywalking.sampleCount | default "500" | quote }}
原来 chart 早就内置了采样,默认 sampleCount: 500(每实例每 3 秒最多 500 条 trace,约 166 条/s)。
2.3 数据到底从哪来的
prod-xc 的 OAP 后端 ES 是 dyck-elasticsearch.tools.svc.cluster.local:9200,dyck 服务上报是集群内地址 dyck-skywalking-oap.tools:11800。结果翻 kjds 服务的 values 时发现,kjds 全部 15 个服务的 backendServices 都是 <VIP>:31800。
把端口和 VIP 对一下就明白了:
<VIP>是 dyck 生产信创环境的 VIP(prod.skywalking.example.com、prod.kibana.example.com都指向它)31800是 dyck OAP gRPC 的 NodePort(prod-xcOAP 里nodePort: 31800)
2.4 看 UI 揪出热点服务
SkyWalking UI 的 Services 页面(kjds 服务组),调用量排前面的几个:
| 服务 | Load (calls/min) | ≈calls/s |
|---|---|---|
| export-service | 148496 | 2475 |
| savefile-service | 53394 | 890 |
| import-service | 17806 | 297 |
| httpsend-service | 13407 | 223 |
再对下副本数:export-service 有 14 副本,savefile-service 6 副本,messageprocess-export-service 12 副本。
三、根因分析
两条原因叠一起,主因是「kjds 跨集群上报 + 高副本服务打满采样」:
- kjds 和 dyck 共用同一套 OAP/ES:kjds 全部服务把 trace 上报到
<VIP>:31800(dyck 生产 VIP + OAP NodePort),数据落dyck-elasticsearch.tools。kjds 没有独立 OAP/ES,查 ES 数据量必须两边一起看。 -
高副本服务把默认采样打满:
sampleCount默认 500(166/s/实例)。export-service14 副本、总 2475/s,平均每副本 177/s 超过 166/s 上限,14 个副本全打满,单服务一天就灌进约 2 亿条 segment。kjds 这边合计贡献约 3.3 亿/天,占 6.6 亿的一半以上,剩下的是 dyck 自己的服务。
四、解决方案
给 kjds 全部 15 个服务的 values.yaml 加 skywalking.sampleCount(和 logging 平级),按「有没有打满采样 + 业务价值」分档:
| 分档 | 服务 | 副本 | sampleCount | 说明 |
|---|---|---|---|---|
| 报文管道(压最低) | export-service | 14 | 10 | 唯一打满采样的大户 |
| 报文管道 | savefile-service | 6 | 20 | 接近打满采样 |
| 报文管道 | httpsend / import / messageprocess-export / systems | — | 30 | 纯报文转发,trace 价值低 |
| 核心业务 | base-service / bigdata-service | — | 100 | 多留点链路方便排查 |
| 其余 | gateway / web / httpquery / httpreceiver / messageprocess-import / mqsend / camel | — | 50 | 通用默认 |
配置写法(在 skywalking: 块下,和 logging: 平级):
skywalking:
enabled: true
collector:
backendServices: <VIP>:31800
logging:
level: ERROR
dir: /AppHome/logs/skywalking-agent
sampleCount: 50 # 每实例每 3 秒最多 50 条 trace
预期 kjds 侧从 ~3.3 亿/天降到 ~4000 万/天,差不多降 85%。
五、验证
第二天对比新 sw_segment-* 索引的文档数和存储大小:
curl -s -u elastic:'<密码>' \
'http://dyck-elasticsearch.tools.svc.cluster.local:9200/_cat/indices/sw_segment-*?h=index,docs.count,store.size&s=index'
预期文档数从 6.6 亿降到 ~1 亿以内(HTTP 和 MQ 两条链路的 segment 都跟着采样被压下去)。
六、注意事项
- MQ 消费也会产生 segment:SkyWalking 的 MQ 插件会追踪每一次 produce/consume,其中 consume 是异步边界、每次消费新建一条 trace,直接堆 segment 数量。采样
sampleCount作用于所有新建 trace,MQ consume 走的是同一条采样逻辑,所以降采样对 MQ 一样有效。 - UI 里的流量数字是 metrics,不是 ES 数据量:Virtual MQ / Services 页面上的
Load、Produce/Consume Traffic是分钟级聚合指标,存sw_metrics类索引,数据量很小;真正撑大 ES 的是这些流量背后每一次调用产生的 segment 明细。 - 还没做:dyck 侧 54 个服务还没降采样;OAP 侧 TTL(
SW_CORE_RECORD_DATA_TTL=1)也没加。后面要是 kjds 降下来、总量还是高,就轮到 dyck 侧了。