⭐️前言⭐️
APP点击某个按钮没有反应/PC端执行某个操作后,响应较慢,通用的问题排查方法:
从多个角度来排查问题
🍉欢迎点赞 👍 收藏 ⭐留言评论
🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言
🍉博客中涉及源码及博主日常练习代码均已上传GitHub
📍内容导读📍
🍅综合排查流程
网络请求和响应的检查
- 使用浏览器开发者工具F12,关注点击按钮后,捕获到的请求的方式(GET/POST)、请求头和请求体是否符合预期
- 查看服务器的响应,检查响应状态码(如200成功、500服务器错误)以及返回的数据内容,确保响应数据符合预期
分离端复现问题
- 前端单独测试:可以在浏览器中将开发者工具的网络连接调为"离线模式"来测试前端逻辑。模拟前端点击操作,查看是否存在接口调用。如果前端逻辑应该在无网络时拦截,但未拦截,说明前端存在问题。
- 后端单独测试:通过工具(比如postman)模拟前端发起API请求,查看后端接口的响应是否符合预期。确保后端在接受到正确的请求时,返回符合业务逻辑的响应
分析慢点
-
定位慢点 :可以通过浏览器控制台抓请求或者记录时间戳的方式,分析延迟主要出现在前端、网络还是后端
-
可以在前端和后端的关键节点记录时间错,通过时间戳的对比定位慢点
-
-
分段日志埋点:在后端的关键逻辑处添加日志记录耗时(比如业务处理开始、结束,数据库查询开始、结束)
-
使用
System.currentTimeMillis()
记录时间差,快速找到耗时长的部分
-
分阶段排查
- 前端慢:关注请求发出前后的逻辑
- 网络慢:检查网络传输与中间层
- 后端慢:逐层检查应用层、数据库和其他依赖服务
协同调试
- 将发现的问题详细记录,包括问题的复现步骤、请求和响应的具体内容、错误日志等,反馈到前后端团队。
- 组织线上调试会议,前后端、测试共同协作,通过共享日志、实时调试来定位问题的根源。
🍅前端角度
1.请求问题:
- 网络延迟:浏览器F12控制台看请求,检查前端到后端的网络路径是否正常,有无高延迟或丢包现象。
- 请求参数问题:确认发送的请求是否携带了过大的数据,或者请求的参数不符合接口要求,导致后端处理异常
- 重复请求:检查前端代码是否因逻辑问题导致发送了重复或无意义的请求
- 请求超时配置:检查前端是否配置了过长的超时时间,未能及时识别问题
2.静态资源问题:
- 如果时静态资源请求慢,可能时前端资源服务器的CDN缓存未命中或者配置问题。
🍅网络层角度
- 网络延迟 :
- 网络带宽不足或延迟过高,特别是服务与数据库、缓存服务分布在不同区域时。
- 数据包丢失或网络不稳定,导致重试或请求失败。
- DNS解析延迟 :
- 服务调用中依赖的域名解析慢,影响请求的实际发出时间。
- 链路复杂 :
- 多层代理(如网关、负载均衡)导致请求经过多个中间环节,增加响应时间。
🍅后端应用层
- 业务逻辑复杂 :
- 业务代码中嵌套调用过多、逻辑判断繁琐,导致请求处理耗时。
- 不必要的循环或递归操作,特别是处理大规模数据时未优化算法。
- 代码优化不足 :
- 代码中存在未优化的阻塞操作(如线程等待、同步锁竞争)。
- 不合理的数据结构选择(如线性搜索代替哈希表)。
- 第三方接口调用慢 :
- 调用外部服务(如支付接口、第三方API)时出现网络延迟或接口响应慢。
- 第三方服务限流或超时未处理,导致阻塞。
- 异常处理问题 :
- 异常处理逻辑不完善,导致未捕获异常不断重试或抛出。
- 缓存问题 :
- 缓存未命中 :
- 请求频率高但未利用缓存优化
- 热数据未加载到缓存,直接从数据库读取数据
- 缓存击穿、雪崩或穿透 :
- 高并发时,缓存过期或被大量无效请求穿透
- 缓存层压力过大,导致失效或阻塞
- 缓存更新策略问题 :
- 缓存未及时更新,导致大量请求命中无效数据并触发数据库查询
- 缓存未命中 :
- 队列与任务调度问题 :
- 消息队列积压 :
- 消息队列(如RabbitMQ、Kafka)中消费速度低于生产速度,导致请求延迟
- 消费者线程数量不足或处理能力有限
- 任务调度延迟 :
- 定时任务频繁触发,导致线程资源耗尽
- 分布式任务调度系统负载不均或出现故障
- 消息队列积压 :
🍅数据层
1.索引问题
- 未建立索引 :
- 查询字段没有建立索引,导致数据库全表扫描
- 索引未命中 :
- 查询条件不符合索引最左前缀原则,联合索引被部分利用
- 查询使用了
LIKE '%xxx'
或函数计算等导致索引失效
- 索引过多或过大 :
- 索引数量过多增加了维护成本
- 大量索引需要更新时,写操作性能降低
2.数据量问题
- 表数据量过大:
- 数据量超过百万行时,查询性能显著下降
- 热点数据和冷数据混合,影响查询效率
- 分页查询耗时:
- 大偏移量分页(比如
OFFSET 100000
)导致性能问题,数据库依然扫描了大量无用数据
- 大偏移量分页(比如
- 历史数据未归档:
- 查询需要扫描包含历史数据的大表
3.SQL语句问题
- 复杂查询:
- 查询包含多表关联(
JOIN
),特别是数据量大的表之间的连接 - 使用子查询(
IN
或NOT IN
),导致数据库多长查询结果集
- 查询包含多表关联(
- 缺乏限制条件:
- 未使用
LIMIT
或条件过滤,导致返回大量无关数据
- 未使用
- 排序和聚合操作:
ORDER BY
和GROUP BY
操作未基于索引,导致全表扫描和排序
4.数据库资源问题
- 连接池不足:
- 数据库连接池耗尽,导致等待队列增加
- 锁等待:
- 并发事务导致锁竞争,如行锁、表锁等待时间过长
- 死锁问题导致查询阻塞
- 缓存失败:
- 查询未命中数据库缓存,必须从磁盘读取数据
5.表结构问题
- 表设计不合理:
- 表字段过多,查询返回冗余数据
- 数据库规范化设计过度,导致频繁的
JOIN
- 分区表未充分利用:
- 查询条件未命中分区键,导致扫描所有分区
优化建议
- 索引优化:设计合理的索引,避免索引失效
- 分库分表:将大表拆分为小表,减少数据量
- 慢查询优化:启用慢查询日志,针对耗时SQL进行调优
- 读写分离:通过主从架构分担查询压力
- 缓存使用:引入Redis、Memcached等缓存层,减少数据库访问
- 事务管理:缩短事务时间,避免长时间锁竞争
🍅系统资源问题
- CPU过载
- 高并发导致CPU使用率过高,线程池处理能力不足。
- 复杂计算任务(如加密解密、文件处理)占用大量CPU资源。
- 内存不足
- 服务内存泄漏或内存溢出,导致频繁GC(垃圾回收)。
- 使用不合理的数据结构,占用大量内存空间。
- 磁盘I/O瓶颈
- 日志写入、文件读写过于频繁,磁盘I/O压力过大。
- SSD或HDD性能不足,影响数据存取效率。
🍅 配置与架构问题
- 线程池配置不合理
- 线程池大小不足,导致请求堆积。
- 超大线程池导致上下文切换成本过高。
- 服务架构问题
- 单体架构无法承受高并发,导致瓶颈。
- 微服务之间调用链过长,服务依赖环节过多。
- 负载均衡策略问题
- 负载均衡未配置健康检查,流量分发到异常实例。
- 负载分配不均,部分节点过载。
🍅优化建议
-
代码层优化:梳理业务逻辑,优化算法与数据结构,移除阻塞代码。
-
数据库优化:索引设计、缓存策略、分库分表、历史数据归档。
-
缓存与队列优化:合理使用缓存,优化队列消费逻辑,监控积压情况。
-
架构优化:通过服务拆分、负载均衡、水平扩展等手段提升服务能力。
-
监控与诊断:通过监控工具或者监控埋点,识别瓶颈,优化慢点。
🍅通用的一些解决手段
- 清除应用缓存,重新登录
- 检查输入是否合理,比如大模型的prompt是否符合要求
- APP可以检查版本是否最新、是否在维护期间
⭐️最后的话⭐️
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁