×

系统慢成狗,开发甩锅网络?手把手教你搭建SkyWalking全链路监控,让性能瓶颈无处遁形!

hqy hqy 发表于2026-02-26 22:04:10 浏览5 评论0

抢沙发发表评论

前两天凌晨三点,手机又是这熟悉的夺命连环call。

爬起来一看,业务群里炸锅了。客服在吼:“用户登录不上去!一直在转圈!” 开发在喊:“我看日志了,没报错啊,服务都活着,CPU 也是绿的,是不是网络抖动了?运维查查交换机?”

那一刻,我手里的保温杯差点没捏碎。网络抖动?每次系统慢查不出原因就赖网络,网络招谁惹谁了?

这种场景,咱干运维的兄弟应该太熟悉了。特别是在现在微服务架构满天飞的年代,一个请求进来,可能要经过网关、A服务、B服务、缓存、数据库、消息队列……中间任何一个环节卡顿,整个请求就崩了。

传统的监控,Zabbix 看看 CPU 内存,ELK 搜搜日志,这时候基本就在抓瞎。因为你不知道这一笔请求,到底死在了哪一步。

这时候,你就需要一把“上帝之眼”,也就是我们要聊的主角——APM(Application Performance Management,应用性能管理)

今天咱们不整那些虚头巴脑的概念,我就带大家从头捋一遍,APM 到底是啥,市面上有哪些能打的开源工具,最后我会手把手教大家搭建一套目前最火的 Apache SkyWalking,让你下次再遇到“系统慢”,直接把证据甩开发脸上:看清楚了,是你这条 SQL 跑了 5 秒,别特么赖网络!

APM 到底是干啥的?

说白了,APM 就是给你的应用程序做“核磁共振”。

以前单体应用时代,代码都在一个包里,哪慢查哪。现在微服务拆得七零八落,服务之间调用关系像一团乱麻。

APM 核心就干三件事:

  1. 1. 链路追踪(Tracing): 就像给每个请求打个“电子标签”(Trace ID)。这个请求从网关进来,经过了哪些服务,调了哪些数据库,每一步花了多少毫秒,全给你记录下来,画成一张瀑布图。
  2. 2. 指标监控(Metrics): 服务吞吐量(CPM)、响应时间(P99/P95)、错误率。这些是宏观数据,告诉你系统健不健康。
  3. 3. 日志关联(Logging): 光知道慢不行,还得知道当时报了啥错。好的 APM 能通过 Trace ID 把上下文日志串起来。

这就好比送快递。没有 APM,你只知道快递发了,最后没收到。有了 APM,你能看到快递几点几分在哪个转运中心,是不是卡在某个仓库(数据库)里出不来了。

开源界的神仙打架:选谁?

市面上开源的 APM 工具其实不少,早些年我也折腾过好几个。

Zipkin
这算是鼻祖了,Twitter 开源的。早几年用的挺多,Spring Cloud 早期官方推荐。但说实话,现在看有点简陋了,界面比较原始,功能也比较单一,基本只能做简单的链路追踪,对代码侵入性虽然不大,但维护起来有点没劲。

Pinpoint
韩国人搞的,基于 Java Agent,如果你全是 Java 技术栈,这玩意儿其实挺强。它的调用链路图画得特别漂亮,粒度非常细。但它有个致命缺点:存储依赖 HBase。兄弟们,维护过 HBase 的都知道,那就是个爹。加上它数据量一大,对服务性能影响比较明显,我们就遇到过装了 Pinpoint 导致服务吞吐量下降 10% 的情况。

Jaeger
CNCF 旗下的,Go 语言写的,云原生亲儿子。如果你是全套 K8s + Istio,用它很顺手。但它的 UI 还是偏极客风,很多运维想要的报表功能它默认没有,得二次开发。

Apache SkyWalking
这是今天要推的主角。国产之光(吴晟大佬主导),现在已经是 Apache 顶级项目。
为啥选它?理由很简单:

  1. 1. 无侵入:Java 应用启动加个参数就行,一行代码不用改。
  2. 2. 多语言:Java, .NET, Node.js, Go, Python 都支持。
  3. 3. 后端灵活:默认用 Elasticsearch 存数据,这玩意儿咱运维都熟,不用去啃 HBase。
  4. 4. 界面炫酷且实用:拓扑图、各种热力图、慢 SQL 排名,老板和开发都爱看。
  5. 5. 社区活跃:文档中文友好,出了 bug 哪怕去 GitHub 提 issue,回复都很快。

所以,这几年我也就基本锁死 SkyWalking 了。

实战:搭建 SkyWalking 全链路监控

光说不练假把式。下面咱们找台机器,实际跑起来。

官网文档:https://skywalking.apache.org/zh/2020-04-19-skywalking-quick-start/#

假设你手头有一台 Linux 服务器(CentOS/Ubuntu 都行),装好了 Docker 和 Docker Compose。如果你还在用源码编译安装,那我建议你赶紧弃暗投明,Docker 部署这东西太香了,版本管理方便,还不污染宿主机环境。

我们这次部署的是 SkyWalking OAP(后端服务) + UI(前端界面),存储使用 Elasticsearch 7.x。

1. 准备 docker-compose.yml

找个目录,比如 /opt/skywalking,建个 docker-compose.yml 文件。

注意啊,这里有个坑。SkyWalking 的版本和 Elasticsearch 的版本是有对应关系的。别瞎配,容易报错。我这里用的是 SkyWalking 9.x 版本,配合 ES 7.10,非常稳。

version: '3.8'
services:

  # 1. 存储层:Elasticsearch

  elasticsearch:

    image:
 docker.elastic.co/elasticsearch/elasticsearch:7.10.2
    container_name:
 elasticsearch
    restart:
 always
    ports:

      -
 9200:9200
    environment:

      -
 discovery.type=single-node
      -
 bootstrap.memory_lock=true
      -
 "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:

      memlock:

        soft:
 -1
        hard:
 -1
    volumes:

      -
 ./es_data:/usr/share/elasticsearch/data

  # 2. 初始化脚本:负责在ES里建表

  oap-init:

    image:
 apache/skywalking-oap-server:9.4.0
    container_name:
 oap-init
    restart:
 on-failure
    entrypoint:
 /bin/sh
    command:
 >
      -c "/skywalking/bin/oapServiceInit.sh && exit 0"
    depends_on:
      -
 elasticsearch
    environment:

      SW_STORAGE:
 elasticsearch
      SW_STORAGE_ES_CLUSTER_NODES:
 elasticsearch:9200

  # 3. 核心后端:OAP Server

  oap:

    image:
 apache/skywalking-oap-server:9.4.0
    container_name:
 oap
    restart:
 always
    ports:

      -
 11800:11800 # gRPC端口,Agent发数据用这个
      -
 12800:12800 # HTTP端口,UI查数据用这个
    depends_on:

      oap-init:

        condition:
 service_completed_successfully
    environment:

      SW_STORAGE:
 elasticsearch
      SW_STORAGE_ES_CLUSTER_NODES:
 elasticsearch:9200
      TZ:
 Asia/Shanghai

  # 4. 前端界面:SkyWalking UI

  ui:

    image:
 apache/skywalking-ui:9.4.0
    container_name:
 skywalking-ui
    restart:
 always
    ports:

      -
 8080:8080
    depends_on:

      -
 oap
    environment:

      SW_OAP_ADDRESS:
 http://oap:12800
      TZ:
 Asia/Shanghai

这里多嘴一句,oap-init 这个 service 是 9.x 之后推荐的做法,专门用来初始化 ES 索引的,跑完就退出了。以前是 OAP 自己启动时检查,但容器化环境下有时候会有时序问题,独立出来更稳。

2. 启动服务

在目录下执行:

docker-compose up -d

这时候你可以去冲杯咖啡。回来后,用 docker-compose logs -f 看看日志,如果没看到 Exception,Elasticsearch 也没报错,那就稳了。

打开浏览器,访问 http://服务器IP:8080

如果你看到了那个蓝色的、充满科技感的登录界面(默认没有密码),恭喜你,地基打好了。现在里面是空的,因为还没接入应用。

3. 接入 Java 应用(Agent 埋点)

这是最关键的一步。

SkyWalking 的强大之处在于 Java Agent。它像一个寄生虫(褒义的),附着在你的 Java 进程上,拦截方法的调用,把数据发给刚才搭建的 OAP Server。

我们需要下载 skywalking-java-agent。去官网下载页面,找 "Java Agent" 的包,下载解压。你会得到一个 skywalking-agent 目录。

这个目录里有个 skywalking-agent.jar,这就是核心。还有一个 config/agent.config,是配置文件。

通常为了省事,我都不改配置文件,直接通过启动命令行的参数来覆盖配置。

假设你的应用叫 user-service,以前的启动命令是:

java -jar user-service.jar

现在,你要改成这样:

java -javaagent:/path/to/skywalking-agent.jar \
     -Dskywalking.agent.service_name=user-service \
     -Dskywalking.collector.backend_service=服务器IP:11800 \
     -jar user-service.jar

看懂了吗?就加了三行东西:

  1. 1. -javaagent:指定探针 jar 包的位置。
  2. 2. service_name:给你这个服务起个名,这名字以后会在 UI 上显示。
  3. 3. backend_service:指定数据发到哪去,就是刚才 docker 部署的那个 OAP 的 11800 端口。

这里有个大坑要注意!
如果你是在 K8s 或者 Docker 容器里跑应用,记得把这个 agent 目录打进你的镜像里,或者通过 Volume 挂载进去。而且 backend_service 的地址一定要保证容器内部能访问通。

我建议先拿个测试环境的服务试刀。重启应用,观察启动日志,如果没有报错,并且应用正常运行,这时候再去 SkyWalking UI 上刷新一下。

见证奇迹的时刻到了。

如何用它揪出性能瓶颈?

一旦数据进来了,你会看到 Dashboard 上的数字开始跳动。咱们来看看怎么用这玩意儿来“打脸”。

1. 拓扑图:上帝视角

点开【Topology】菜单。你会看到一张网状图。

如果你的系统是微服务架构,这里会非常壮观。你会看到 User 服务调了 Order 服务,Order 服务调了 Redis 和 MySQL。

这时候,如果某条连线变成了红色,不用想,那条链路出问题了。可能是报错多,也可能是响应太慢。鼠标放上去,直接显示平均耗时。以前开发老问“是不是数据库挂了?”,现在你指着屏幕说:“看,数据库这儿是绿的,但是你调第三方支付接口这根线是红的,耗时 5 秒,是你代码逻辑在等回调,懂?”

2. 链路追踪:显微镜分析

这是最实用的功能。点开【Trace】菜单。

如果你接到了用户投诉,说“刚刚点了一次保存,卡了半天”。
如果用户能提供报错时间,或者你有日志里的 TraceID,直接搜。如果没有,就在右边的时间轴上找那个耗时特别长的请求。

点开那个长条,你会看到一个瀑布流。

这个瀑布流详细到了什么程度?
它会显示:

  • • Spring Controller 接收请求(0ms)
  • • Service 业务逻辑处理(5ms)
  • • JDBC Execute Statement(2000ms)
  • • Return(2ms)

看到那个 2000ms 的红条了吗?点开它。
SkyWalking 会直接把当时执行的那条 SQL 语句展示给你看! 甚至连参数都能通过配置开启显示。

这时候你就可以截图发群里了:“来来来,谁写的这条 SQL?全表扫描,没走索引,跑了 2 秒。赶紧优化去,别在这怀疑服务器 CPU 负载高了。”

这就叫有理有据,令人信服

3. 性能剖析(Profile):代码级的深究

有时候,不是 SQL 慢,是代码逻辑慢。比如写了个死循环,或者正则匹配效率太低。这时候瀑布图只显示“Service 方法耗时 2 秒”,但不知道哪行代码慢。

SkyWalking 有个高级功能叫【Profile】。
你可以新建一个任务,指定监控某个 Endpoint(接口)。当这个接口再被调用时,它会把线程栈抓下来。

分析结果会精确地告诉你:com.company.service.OrderService.calculatePrice() 这个方法里的第 45 行,消耗了 CPU 500ms。

这简直就是远程 Debug 神器,开发看了都得给你递烟。

生产环境落地的几个“坑”

虽然 SkyWalking 很爽,但在生产环境大规模铺开,我有几条血泪经验得嘱咐你:

1. 采样率设置
默认情况下,Agent 可能会采集所有请求。如果你的业务量是几万 QPS,全量采集会把你的 ES 存爆,带宽也会吃紧。
在 agent.config 里有个配置 agent.sample_n_per_3_secs。意思是每 3 秒采集多少条。或者配置采样率比例。
通常生产环境,我们需要的是趋势和异常,不需要每一条都留底。建议开启采样,只留个 10%-20%,或者配置成只采集慢请求和错误请求。

2. 数据清理(TTL)
ES 里的数据是海量的。OAP 有个配置叫 recordDataTTL 和 metricsDataTTL
Trace 数据(那张瀑布图)最占空间,一般保留 3-7 天就够了,没人会去查上个月的慢请求。Metrics 指标数据可以留长点,比如 30 天,用来做月度报表。
别贪多,否则你的磁盘报警会让你夜不能寐。

3. 忽略心跳接口
很多服务都有 /health 或者 Eureka/Nacos 的心跳包,一秒钟好几次。这些数据毫无价值,还会弄脏拓扑图。
记得在 agent 配置里把这些路径加入 trace.ignore_path,眼不见心不烦。

4. 报警规则
SkyWalking 自带报警功能(Alarm)。你可以配置规则,比如“过去 3 分钟内,某个服务的平均响应时间超过 500ms”。它支持 Webhook。
我一般的做法是写个简单的中间件,接收这个 Webhook,然后转成钉钉或飞书消息发到运维群里。这样一旦有慢服务,我们比用户先知道。

总结

运维这行,做到最后其实就是比谁手里的工具更锋利。

以前我们是“背锅侠”,系统一慢就是我们的锅。有了 APM,我们变成了“裁判员”。

SkyWalking 不仅仅是一个监控工具,它打通了开发和运维之间的那堵墙。当大家都看着同一张拓扑图,看着同一个 Trace 详情时,沟通成本会直线下降。

搭建这一套东西,快的话半小时,慢的话半天,但它能为你节省的排查时间,可能是以后几年的无数个通宵。

这波干货如果不收藏,下次系统崩了可别怪我没提醒你啊。

兄弟们,如果你在搭建过程中遇到啥奇怪的报错,或者对 ES 的调优拿不准,欢迎在评论区留言。咱们一起探讨,绝不藏私。

最后,码字不易,全是实战里摸爬滚打出来的经验。觉得有用的话,点个关注,转发给身边的运维兄弟和开发同事(特别是那个爱甩锅的)。


打赏

本文链接:https://kinber.cn/post/6280.html 转载需授权!

分享到:


推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

 您阅读本篇文章共花了: 

群贤毕至

访客