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

前言

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

问题分析

    处理问题的第一步就是场景复现,本地打开网站看了一下确实如此.简单描述一下问题场景:这里面有一个根据会员姓名或是手机号或是卡号模糊查询会员信息的接口,选中用户简要信息之后会显示用户的详情信息,每次输入一个字符之后会调用接口进行查询,有点类似于百度中输入搜索词之后会显示相关联的搜索词.业务截图如下:
在这里插入图片描述
    以下截图为输入多次字符时的调用接口查询情况,由于已经对服务端存在问题做过处理,所以显示的状态都是200,修改之前都是等待状态:pending.
在这里插入图片描述
    分析之后主要存在两个问题:

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项目进行优化。
    以上是处理网站性能优化的记录和总结,如果看完感觉有所收获环境评论区点赞或留言!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卖柴火的小伙子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值