一次后台管理系统加载慢问题定位过程

这是我参与更文挑战的第15天,活动详情查看: 更文挑战

我们的系统是基于花裤衩开源的vue-elementui-admin做的。运营人员反馈线上管理系统卡顿严重,在用户量上来之后需要优化。

卡顿现象

经过线上测试,卡顿可重现,但不可稳定重现。

卡顿现象主要表现为:

  1. 点击菜单,菜单页Tagview加载慢,可以看到上方缓慢的加载条。
  2. 页面打开后,数据加载慢。

思路

宏观上讲,卡顿分为两部分:

  1. 后端接口延迟:卡顿2的主要原因。
  2. 前端静态资源加载慢:暂不清楚,需定位。

后端接口卡顿定位

后端接口卡顿定位主要有两种,一种是通过后端拦截器记录每个接口的响应时间,一种是通过前端浏览器Network查看各请求的整体响应时间。

下图为后端记录格式:

image.png

下图为前端查看请求响应时间:

image.png

我们发现有部分接口的响应时间(Waiting-TTFB)非常长,确实需要优化,我们针对这部分接口分别进行后端的优化。

后端优化方案:

​ 可以通过优化执行语句,并发,Sql优化,缓存来达到后端接口优化的目的,这部分不多言。

前端资源加载监听

后端接口延迟会造成页面加载后,数据持续加载,但理论上不应该造成页面初始加载的卡顿。

我们认为主要的卡顿原因在前端。

通过Chrome-Network监听发现,页面卡顿时,部分接口的QueueingStalled时间非常长,但延迟并不十分稳定。查找资料吧。

Network features reference中,View the timing breakdown of a request一节中的Timing breakdown phases explained,介绍了各个概念,原文如下:

Here’s more information about each of the phases you may see in the Timing tab:

  • Queueing

. The browser queues requests when:

  • There are higher priority requests.

  • There are already six TCP connections open for this origin, which is the limit. Applies to HTTP/1.0 and HTTP/1.1 only.

  • The browser is briefly allocating space in the disk cache

  • Stalled. The request could be stalled for any of the reasons described in Queueing.

  • DNS Lookup. The browser is resolving the request’s IP address.

  • Initial connection. The browser is establishing a connection, including TCP handshakes/retries and negotiating an SSL.

  • Proxy negotiation. The browser is negotiating the request with a proxy server.

  • Request sent. The request is being sent.

  • ServiceWorker Preparation. The browser is starting up the service worker.

  • Request to ServiceWorker. The request is being sent to the service worker.

  • Waiting (TTFB). The browser is waiting for the first byte of a response. TTFB stands for Time To First Byte. This timing includes 1 round trip of latency and the time the server took to prepare the response.

  • Content Download. The browser is receiving the response.

  • Receiving Push. The browser is receiving data for this response via HTTP/2 Server Push.

  • Reading Push. The browser is reading the local data previously received.

我们重点关注其中耗时较长的Queueing,Stalled,Waiting(TTFB)以及可优化的部分。翻译如下:

Queueing

浏览器在以下情况将请求排队:

 1. 有更高优先级的请求。
 2. 已经为此源打开了六个 TCP 连接,这是限制。仅适用于 HTTP/1.0 和 HTTP/1.1。
 3. 浏览器在磁盘缓存中短暂分配空间

Stalled:当Queueing中的任何情况发生时,请求将被Stalled

**Waiting (TTFB)**:等待初始响应所用的时间,也称为第一字节时间。此时间将捕捉到服务器往返的延迟时间,以及等待服务器传送响应所用的时间。

Queueing与Stalled的区别

StalledQueuing之后的下一个状态,Stalled开始时已经出队,他们太显著的差别(是否使用proxy/ssl),他们之间没有and/or/parent/child的关系,有建议将queueing/stalled改名为postponed/awaiting socket,具体可以看看chromium issue。[2]

Queueing

优化方向:(服务器同一个源/域最多同时又6个TCP连接)

1. 减少请求数
2. 域名发散:把资源放到不同的域名上

Stalled

同源链接复用可能引发这样的问题,由于之前存在可用链接,此时浏览器希望重用之前的连接以节省资源,用之前的一个socket去发起连接,后收到服务器返回的链接已重置/不存在,再从原本可用链接中找可用链接,引发长时间等待,具体可以看看 chrome-stalled-problem-resolving-process

Stalled是从TCP连接建立完成,到真正可以传输数据之间的时间差。TCP三次握手后,发送端发送数据后,一段时间内(不同的操作系统时间段不同)接收不到服务端ACK包,就会以 某一时间间隔(时间间隔一般为指数型增长)重新发送,从重传开始到接收端正确响应的时间就是stalled阶段。而重传超过一定的次数(windows系统是5次),发送端就认为本次TCP连接已经down掉了,需要重新建立连接。 stalled阶段时TCP连接的检测过程,如果检测成功就会继续使用该TCP连接发送数据,如果检测失败就会重新建立TCP连接。所以出现stalled阶段过长,往往是丢包所致,这也意味着网络或服务端有问题。

文章[4]详细描述了作者定位一个Stalled延时长的问题。

一种可能的Stalled延迟过长的情况是:

我新开一个标签尝试访问同一个资源的时候,这次请求也会去读取这个缓存,假设之前那次请求很慢,耗时很久,那么后来这次请求因为无法获取对该缓存的操作权限就一直处于等待状态。

两种解决方案:

  1. 服务端设置Response响应头Cache-Control: no-cache。即无缓存。
  2. 给请求添加时间戳让每次请求变得唯一。

Waiting (TTFB)

建议将此值控制在200毫秒以下[3]。长TTFB会揭示两个主要问题:

  1. 客户端与服务端之间的网络条件较差;
  2. 服务器应用的响应慢

DNS Lookup

DNS查询所用的时间

  • 可优化部分
    • 不要有太多的新域名(可能递归查询绕地球一圈),参考域名收敛
    • 减少DNS解析路径(如果内部有很多DNS服务器解析)。

优化汇总

主要优化方向

  1. 减少请求数+域名发散解决Queueing时长问题
  2. 禁用缓存,或请求时间戳解决Stalled时长问题
  3. 优化服务端响应(具体见上述后端优化方法),解决TTFB时长问题

后续优化方向需要学习具体的的Chrome的请求分析来做。参考[4]与Chrome官网。

[1] 了解资源加载时序

[2] Network Resource Timing 我的请求慢在哪

[3] Chrome DevTools 的 Queueing、Stalled解析

[4] 关于请求被挂起页面加载缓慢问题的追查