网页性能优化实战之CPU拉满问题处理

简介: 今天测试小哥屁颠屁颠的找过来说查询会员信息这块访问速度很慢,之前没有问题,现在输入信息之后根本就没有反应.要等好好长时间才行.另外点击其他页面都是显示网络连接异常,感觉整个系统都会崩溃了。每次测试找过来都当做是对自己的一次技术提升,尤其是对和业务逻辑关联不高的问题更感兴趣,哈哈!现在把问题分析以及处理过程简单记录一下,希望对有相同线上问题的同学能提供一些解决思路.

前言


   今天测试小哥屁颠屁颠的找过来说查询会员信息这块访问速度很慢,之前没有问题,现在输入信息之后根本就没有反应.要等好好长时间才行.另外点击其他页面都是显示网络连接异常,感觉整个系统都会崩溃了。每次测试找过来都当做是对自己的一次技术提升,尤其是对和业务逻辑关联不高的问题更感兴趣,哈哈!现在把问题分析以及处理过程简单记录一下,希望对有相同线上问题的同学能提供一些解决思路.


问题分析


   处理问题的第一步就是场景复现,本地打开网站看了一下确实如此.简单描述一下问题场景:这里面有一个根据会员姓名或是手机号或是卡号模糊查询会员信息的接口,选中用户简要信息之后会显示用户的详情信息,每次输入一个字符之后会调用接口进行查询,有点类似于百度中输入搜索词之后会显示相关联的搜索词.业务截图如下:

5d13eab9743fc1299fd74137dcef9972_b025cf4166ee480b9c698a1ec5e7703c.png

   以下截图为输入多次字符时的调用接口查询情况,由于已经对服务端存在问题做过处理,所以显示的状态都是200,修改之前都是等待状态:pending.

c7dfcfe54f71bffd76ad28a29e115dc2_d0c31f64242847abada42f277858d949.png

   分析之后主要存在两个问题:


1.接口调用过于频繁

   每次输入一个字符都进行接口调用,如果手速快的话对服务器冲击得多大.看过百度或是谷歌的关联词查询,人家那么高的服务器配置都不敢输入一个字符接着去调用一次服务端,中间需要间隔一定的时间,具体的间隔调用时间可以根据数据量进行调整,以不影响用户体验为要求.这种处理方式在前端叫做节流处理,简单意思就是说在指定的时间段内不限制用户数输入的字符数,能输入几个算几个,但是限制只允许调用一次接口,接口响应之后才会发起下次请求.这样就大大减少了对服务器的冲击;


2.单个接口查询查询速度过慢

   只输入一个字符之后响应时间很长,看了一下控制台的响应时间大概是15秒.猜测此处存在慢sql.


问题处理


   对于问题1主要是前端访问方式的处理,问题分析中已经将处理方式做了说明,此处不再多说。主要是从服务端说一下问题2的处理过程.

   以下是此场景的数据库查询sql:

SELECT DISTINCT(staff_card.`card_no`) card_no,staff.`real_name`,staff.`mobile`,card.`card_name`,staff_card.`status`,card.id card_id
    FROM studio
    LEFT JOIN staff ON staff_studio.`login`=staff.`login`
    LEFT JOIN staff_card ON staff_card.`login`=staff.`login`
    LEFT JOIN card ON staff_card.`card_id`=card.`id`
    LEFT JOIN card_course ON card_course.`card_id`=staff_card.`card_id`
    WHERE ((staff_studio.`state`=1  
  AND staff_studio.`studio_id`=2 AND staff_card.`studio_id`=2) 
    OR (card.`flag`=1 AND  card_course.`studio_id`=2 ))
    AND staff_card.`status` IN (1,4)
    AND CONCAT(staff.`mobile`,staff.`real_name`,staff_card.`card_no`)  LIKE CONCAT('%', '1','%')


   数据库执行时间在11秒.

使用explain进行执行计划查询,发现type字段中有多个all,表示是全表扫描,经过多次尝试,主要做两个处理:


1.使用union all 代替or

SELECT 
taff_card.`card_no`,staff.`real_name`,staff.`mobile`,card.`card_name`,staff_card.`status`,card.id card_id
        FROM staff_studio
        LEFT JOIN staff ON staff_studio.`login`=staff.`login`
        LEFT JOIN staff_card ON staff_card.`login`=staff.`login` AND staff_card.`studio_id`=staff_studio.`studio_id` AND staff_card.`status` IN (1,4)
        LEFT JOIN card ON staff_card.`card_id`=card.`id`
        WHERE staff_studio.`state`=1  AND staff_studio.`studio_id`=2 
        AND CONCAT(staff.`mobile`,staff.`real_name`,staff_card.`card_no`)  LIKE CONCAT('%', ‘1’,'%')
 UNION ALL 
 SELECT 
staff_card.`card_no`,staff.`real_name`,staff.`mobile`,card.`card_name`,staff_card.`status`,card.id card_id
        FROM staff_studio
        LEFT JOIN staff ON staff_studio.`login`=staff.`login`
        LEFT JOINstaff_card ON staff_card.`login`=staff.`login`
        LEFT JOIN card ON staff_card.`card_id`=card.`id`
        LEFT JOIN card_course ON card_course.`card_id`=staff_card.`card_id`
        WHERE card.`flag`=1 AND  card_course.`studio_id`=2 
        AND staff_card.`status` IN (1,4)
        AND CONCAT(staff.`mobile`,staff.`real_name`,staff_card.`card_no`)  LIKE CONCAT('%', ‘1’,'%')


2.添加索引

   将explain查询中type为all的表按照查询条件或left关联字段进行添加索引,执行sql如下:

-- manage_staff_studio添加索引login
ALTER  TABLE  manage_staff_studio  ADD  INDEX  index_login (login);
-- manage_staff_card添加索引login
ALTER  TABLE  manage_staff_card  ADD  INDEX  index_login (login);
-- manage_card_course添加索引card_id
ALTER  TABLE  manage_card_course  ADD  INDEX  index_card (card_id);

添加之后测试查询速度变为0.029秒;慢sql问题处理


反思总结


   由于业务设计原因,对于个别字段存在重复情况,原来使用distinct进行处理,但是使用explain查询之后发现extra中存在using temporying.查询了相关资料得知using temporying一般是进行distinct或是group by操作都会导致生成临时表,一般出现临时表是需要优化的,但是想说的是凡事没有绝对,别人说的结论自己动手要去尝试验证。只要查询速度能提升上来,出现此提示不处理也可以.后期如果需要对distinct优化等同于group by进行优化,官方文档中对此有所介绍.官方参考链接:

https://dev.mysql.com/doc/refman/8.0/en/distinct-optimization.html

   另外说一下线上业务场景与问题定位的思路,对于服务端而言,服务端项目所部署的服务器和数据库所在服务器可能不是一个,需要分别对对应的服务器进行查看监控信息,项目中服务器都是使用的阿里云,可以通过阿里云控制台看下各项监控信息.上面的场景中存在的问题还在于发起很多个请求没有响应的情况下,打开别的页面会出现网络异常提示,对应时间节点看数据库服务器监控信息,当时CPU已经达到100%.所以其他页面不能打开也就能解释清楚了。

   如果想看详细的服务器信息可以使用atop工具进行监控,可以实时输出监控日志信息,结合服务端项目业务日志更容易进行定位问题。atop安装参考链接:

https://help.aliyun.com/document_detail/101877.html

   cpu达到100%处理方案:1.升级CPU,2.业务侧优化,主要服务器上各应用CPU占比,针对性优化.一般是对数据库或是java项目进行优化。

   以上是处理网站性能优化的记录和总结,如果看完感觉有所收获环境评论区点赞或留言!


相关文章
|
6月前
|
人工智能 并行计算 PyTorch
【PyTorch&TensorBoard实战】GPU与CPU的计算速度对比(附代码)
【PyTorch&TensorBoard实战】GPU与CPU的计算速度对比(附代码)
346 0
|
安全 Windows
一次简单的服务器 cpu 占用率高的快速排查实战
一次简单的服务器 cpu 占用率高的快速排查实战
|
1月前
|
监控 并行计算 数据处理
构建高效Python应用:并发与异步编程的实战秘籍,IO与CPU密集型任务一网打尽!
在Python编程的征途中,面对日益增长的性能需求,如何构建高效的应用成为了每位开发者必须面对的课题。并发与异步编程作为提升程序性能的两大法宝,在处理IO密集型与CPU密集型任务时展现出了巨大的潜力。今天,我们将深入探讨这些技术的最佳实践,助你打造高效Python应用。
37 0
|
4月前
|
并行计算 监控 数据处理
构建高效Python应用:并发与异步编程的实战秘籍,IO与CPU密集型任务一网打尽!
【7月更文挑战第16天】Python并发异步提升性能:使用`asyncio`处理IO密集型任务,如网络请求,借助事件循环实现非阻塞;`multiprocessing`模块用于CPU密集型任务,绕过GIL进行并行计算。通过任务类型识别、任务分割、避免共享状态、利用现代库和性能调优,实现高效编程。示例代码展示异步HTTP请求和多进程数据处理。
56 8
|
6月前
|
机器学习/深度学习 并行计算 Android开发
Int8量化算子在移动端CPU的性能优化
Int8量化算子在移动端CPU的性能优化
191 0
|
6月前
|
运维 Linux Docker
Docker详解(十一)——Docker容器CPU资源限额实战Docker详解
Docker详解(十一)——Docker容器CPU资源限额实战
144 5
|
6月前
|
缓存 编译器 调度
【C/C++ 性能优化】了解cpu 从而进行C++ 高效编程
【C/C++ 性能优化】了解cpu 从而进行C++ 高效编程
358 0
|
6月前
|
XML Java API
Android App开发之创建JNI接口获取CPU指令集讲解及实战(附源码 简单易懂)
Android App开发之创建JNI接口获取CPU指令集讲解及实战(附源码 简单易懂)
205 0
|
C++ 索引 Windows
调试实战——程序CPU占用率飙升,你知道如何快速定位吗?
程序CPU占用率飙升,你知道如何快速定位吗?
|
9天前
|
弹性计算 Kubernetes Perl
k8s 设置pod 的cpu 和内存
在 Kubernetes (k8s) 中,设置 Pod 的 CPU 和内存资源限制和请求是非常重要的,因为这有助于确保集群资源的合理分配和有效利用。你可以通过定义 Pod 的 `resources` 字段来设置这些限制。 以下是一个示例 YAML 文件,展示了如何为一个 Pod 设置 CPU 和内存资源请求(requests)和限制(limits): ```yaml apiVersion: v1 kind: Pod metadata: name: example-pod spec: containers: - name: example-container image: