如何快速排查线上问题 -copy qf
排查流程图
flowchart TB
A --> B --> C --> D --> E
subgraph A[认识问题]
A1[收集信息]
A2[确认问题]
A3[复现问题]
A4[影响范围]
A1 --> A2 --> A3 --> A4
end
subgraph B[诊断/确认问题]
B1[检查网络连接]
B2[查看浏览器控制台]
B3[捕获HTTP请求和响应]
B4[查看页面加载性能]
B5[检查兼容性问题]
B6[检查npm库版本]
B7[问题上升高度]
B1 --> B2 --> B3 --> B4 --> B5 --> B6 --> B7
end
subgraph C[解决问题]
C1[服务端问题]
C2[前端代码逻辑问题]
C3[自由库问题]
C4[第三方库问题]
C1 --> C2 --> C3 --> C4
end
subgraph D[验证修复和发布]
D1[验证修复效果]
D2[代码审查]
D3[部署和发布]
D4[用户反馈]
D1 --> D2 --> D3 --> D4
end
subgraph E[总结和文档]
E1[记录解决过程]
E2[更新文档]
E3[回顾和学习]
E1 --> E2 --> E3
end
认识问题
收集信息
首先,需要收集尽可能多的信息来了解问题的全貌。这一步至关重要,因为收集到的信息越具体,后续的排查和解决过程就会越高效。
- 用户反馈
- 直接沟通:通过支持渠道,例如钉钉/电话等,获取用户对问题的描述。
- 用户截图和录像:要求用户提供问题出现时的截图或录屏,以直观了解问题现象。
- B端用户:可以直接联系用户,引导打开控制台,直接查看报错信息
- 网络状态:了解用户的网络连接情况,是否在使用代理,网络速度等信息。
- 灰度情况:排除是否因灰度导致。
- AEM日志文件
- 前端日志:确保前端代码中有足够的日志记录,在需要时可以通过控制台或调试工具获取日志信息。
- 监控平台日志:如果使用了监控平台(如 Sentry、Datadog),直接查看平台上报告的错误和异常。
- 浏览器和操作系统,浏览器版本,应用发布版本等。
- 关注AEM群消息:养成良好的习惯,定期查看AEM异常信息,
- 新增异常:需要排查是否可能为发布导致,优先排查解决,避免问题升级。
- top异常:专项解决,避免升级成工单。
- 用户流信息:收集用户访问路径、点击行为、操作日志等数据,获取用户操作的全流程记录。
确认问题/影响范围
在收集到问题信息后,需要明确问题的具体表现和范围。这一步包括确定问题的影响面,以及是否与特定条件或环境相关。
- 问题确认
- 问题可重复性:确认是否能在相同条件下多次复现问题。
- 示例: 在同一个浏览器和操作系统中,依照用户描述执行相同的步骤,观察是否每次都会出现相同的错误。
- 错误类型及表现:将问题分类,例如页面崩溃、布局错误、功能失效等,并详细描述其表现。
- 确认影响范围
- 是否全局性或局部性:检查问题是否只在某些地区或用户群体中出现。
- 特定页面或全站问题:确认问题是否只在某些特定页面或全站范围内发生。
- 特定功能:确定问题是否与某些具体功能或模块相关,比如下单/列表展示等。
- 特定时间段:确认问题是否在特定时间段内出现
- 示例:问题是否只在高峰期间发生
- 时间范围
- 最近变动:确认问题是否与最近的代码更新、配置变更或第三方服务变动有关。(90%以上的问题,都是由最新发布导致)。
- 历史问题:判断问题是否之前存在,这是新出现的问题还是长期存在的隐患。查找历史日志和错误报告,确认问题是否曾经多次出现。
复现问题
明确问题后,尽量在你自己的开发环境或测试环境中复现问题。这有助于找到问题的根本原因并制定解决方案。
- 重现步骤
- 详细步骤记录:根据用户提供的信息,记录重现问题的详细步骤。这些步骤应尽量详细,确保每次执行都能复现问题。
- 环境模拟
- 相同浏览器和操作系统环境:在用户报错的相同环境中重现问题(可以使用虚拟机、浏览器模拟工具等)。
- 网络条件模拟:使用网络限制工具模拟不同的网络状态(例如慢速网络或高延迟环境)来重现问题。
- 浏览器开发工具
- 启用开发者工具:使用 Chrome DevTools 或其他浏览器开发工具来观察控制台输出、网络请求、DOM 和样式变化。
- 设置断点:在怀疑有问题的代码位置设置断点,通过逐步执行代码来排查问题。
- 日志和错误分析
- 查看控制台日志:分析控制台中的错误日志,确定具体报错信息和出错的代码位置。
- 抓包分析:使用抓包工具(如 Charles、LightProxy)分析 HTTP 请求和响应,查看是否有异常。
- 服务端配合
- 服务端修改数据库:部分场景需要服务端改库才能复现的,请求服务端协助。(一切资源都是你排查问题的手段)。
诊断/确认问题
确定问题原因,问题解一半。
检查网络连接
确保用户的网络连接没有问题是排查线上问题的第一步,因为许多前端问题可能是由于网络延迟、连接不稳定等原因导致。
- 用户网络状态检查
- 排除CDN或第三方服务问题
- 主应用中包含很多 <script src="xxx" /> 引入方式,检查资源访问是否正常
- 检查用户是否使用最新app版本
- 灰度状态下,检查用户是否在灰度内
查看浏览器控制台
浏览器控制台是排查前端问题的重要工具,它可以提供关于页面加载、脚本执行等各方面的详细信息。
- 分析常见问题
- 引导用户打开控制台
- B端用户:可以直接联系用户,引导打开控制台,直接查看报错信息
- SourceMap
- AEM查看错误堆栈信息
- 本地使用sourcemap调试
捕获HTTP请求和响应
HTTP 请求和响应的状态和内容可以提供大量排障信息,特别是涉及到数据的加载和交互问题。
- 分析常见问题
-
400 Bad Request
描述:服务器无法理解请求的格式,因为请求有错误或不正确的语法。
解决方案:检查并确保请求的URL和参数格式正确。检查请求头部和请求体是否符合API规范。清除浏览器缓存和Cookie。
401 Unauthorized
描述:请求要求身份验证。客户端必须提供正确的认证凭据。
解决方案: 确保正确的身份验证信息(如API Key、Token)已包含在请求中。 检查认证凭据是否过期,如果过期,重新获取新的凭据。 确认用户具有访问资源的权限。
403 Forbidden
描述:服务器理解请求但拒绝执行。
解决方案:确认用户是否有权限访问请求的资源。检查服务器上相关文件或目录的权限设置。若使用白名单机制,确保客户端IP地址在白名单中。
404 Not Found
描述:服务器找不到请求的资源。
解决方案:检查请求的URL是否正确。确认资源是否存在或者是否已被移动。检查路由和路径配置是否正确。
500 Internal Server Error
描述:服务器遇到错误,无法完成请求。解决方案:检查服务器端代码和日志,以找出错误的具体原因。确保服务器资源(如内存、CPU)充足,检查是否有系统资源问题。检查服务器配置和依赖项是否正确。
502 Bad Gateway
描述:作为网关或代理的服务器从上游服务器收到无效响应。
解决方案:检查上游服务器(如应用服务器、数据库服务器)是否正常运行。检查网络配置和防火墙设置,确保服务器之间的通信正常。重新启动相关服务或服务器。
503 Service Unavailable
描述:服务器目前无法处理请求,因为它暂时过载或进行维护。
解决方案:检查服务器资源使用情况,解决可能的过载问题。确认服务器是否在进行维护,并等待维护结束。配置适当的负载均衡机制来分配负载。
504 Gateway Timeout
描述:作为网关或代理的服务器没有及时从上游服务器收到响应。
解决方案:检查上游服务器的响应时间,确保其性能正常。优化上游服务器的查询或处理逻辑以加快速度。检查网络连接,确保无延迟或中断。这些是一些常见的HTTP错误及其可能的解决方案。具体问题需要具体分析,可以通过检查服务器日志、调试代码和改善网络设置来解决问题。
- 抓包分析
- 使用抓包工具(如 Charles、Fiddler)捕获和分析 HTTP 流量,以更详细地查看请求和响应的内容和头部信息。 通过抓包工具,可以模拟不同的网络环境,进行深度分析,例如查看 HTTPS 加密的详细内容。
- 利用好traceId,让服务端协助我们去解决问题。
- 熟悉微服务架构
- 熟悉微服务架构,了解发起请求的整个链路,确认问题可能出现在哪个环节。
- 示例:熔断/限流/降级等
- 服务端相关问题
- API接口问题
- 检查 API 响应状态码,例如 500(服务器内部错误)、502(网关错误)、503(服务不可用)、504(网关超时)。 与后端开发人员沟通,提供错误日志和请求示例,明确问题所在。 使用 Postman 或 cURL 模拟请求,查看是否能在开发环境中复现问题。 检查 API 文档(max),确保前端调用参数和数据格式正确。
- 数据库问题
- 服务器配置问题
- 检查服务器配置是否正确,例如 HTTP 头部、缓存策略、负载均衡等。 使用服务器日志(如 Nginx、Apache 日志)分析服务器运行状态和错误信息。
- 服务端性能问题
- 使用性能监控工具,查看服务器性能状态,
- 如 CPU、内存、网络、QPS、尖刺等
检查页面加载性能
页面加载缓慢或资源加载失败可能会影响用户体验,需要通过性能检查找到瓶颈和问题。
- 分析常见问题
-
大量的初始资源加载
问题: 初始加载时需要加载大量的JavaScript、CSS和图片文件,导致页面加载时间过长。
解决方案: 使用代码拆分(Code Splitting)和按需加载(Lazy Loading)来减小初始加载的资源大小。 使用React.lazy和Suspense进行组件的懒加载。 使用webpack等工具进行资源的按需打包。
非优化的图片资源
问题: 大量高分辨率且未压缩的图片会显著增加页面加载时间。
解决方案: 压缩图片,使用WebP等现代图片格式。 使用图片懒加载(Lazy Load Images)技术,只在需要时加载图片。 使用响应式图片(Responsive Images)技术,加载合适大小的图片。
未压缩的静态资源
问题: 未压缩的JavaScript和CSS文件会增加加载时间。
解决方案: 使用gzip、Brotli等压缩技术对静态资源进行压缩。 在生产环境中启用CSS和JavaScript的最小化(Minification)和压缩。
不必要的重渲染
问题: 一些不必要的组件重渲染会导致性能下降。
解决方案: 使用React.memo或PureComponent来避免不必要的重渲染。 使用shouldComponentUpdate生命周期方法进行手动优化。 使用React的性能分析工具(如React Profiler)找出性能瓶颈。
长时间的JavaScript执行
问题: 复杂的JavaScript逻辑和大量的计算会阻塞主线程,导致页面卡顿和加载延迟。
解决方案: 优化繁重的JavaScript逻辑,使用Web Workers来进行后台处理。 使用防抖(Debouncing)和节流(Throttling)技术来减少事件触发频率。 使用虚拟列表(Virtualized Lists)来优化长列表的渲染。
使用不当的第三方库
问题: 引入和使用大量的第三方库会增加应用的体积并可能导致性能问题。
解决方案: 去掉不必要的库,用原生JavaScript或轻量级的替代品。 动态引入第三方库,使用如React Loadable等工具进行按需加载。
非高效的样式处理
问题: 使用大量的CSS-in-JS解决方案或者不高效的样式处理会影响性能。
解决方案: 使用静态提取的CSS,减少运行时的样式计算。 优化CSS选择器的复杂度,避免使用过于嵌套的选择器。
HTTP请求过多
问题: 页面加载时发起大量的HTTP请求,增加服务器负载和页面加载时间。
解决方案: 合并资源文件(如CSS和JS文件)。 使用HTTP/2,允许多个请求在一个连接上并行完成。 使用CDN缓存静态资源,减少服务器负担和加快加载速度。 通过这些方法和技巧,可以显著提升React前端页面的加载性能,带来更好的用户体验。
常见解决方案
使用浏览器开发者工具
Chrome DevTools 和 Firefox Developer Tools 提供了一些非常强大的工具来帮助你识别和分析性能瓶颈。
Performance(性能)面板
打开开发者工具(通常通过按 F12 或 Ctrl+Shift+I)。
找到并打开Performance面板(在Chrome中,名称可能有所区别)。
点击录制按钮,进行页面操作以触发长时间执行的JavaScript代码。
停止录制,查看时间线,找到时间消耗过多的脚本部分。你可以点击展开每个部分,查看具体的函数调用栈。
Profiler(分析)面板
打开Profiler面板。
点击录制按钮,进行页面操作,触发长时间执行的JavaScript代码。
停止录制并查看分析结果,找到性能瓶颈。
和
可以在长时间执行的代码区域添加
console.time
和console.timeEnd
来测量具体代码块的执行时间console.time('longRunningCode'); // 要测量的代码块 console.timeEnd('longRunningCode');
性能优化技巧
优化算法和数据结构确保你使用的是高效的算法和合适的数据结构。有时候,简单的代码重构就能显著提高性能。
使用requestAnimationFrame
如果代码中有需要重复执行的任务(如动画),使用requestAnimationFrame代替setTimeout或setInterval,以更好地协调任务与浏览器的刷新周期。
function animate() { // 动画逻辑 requestAnimationFrame(animate); } requestAnimationFrame(animate);
使用Web Workers
对于CPU密集型任务,如复杂计算,可以将其移到Web Workers中。Web Workers在后台线程执行,不会阻塞主线程。(还可以考虑WASM)
const worker = new Worker('worker.js'); worker.postMessage(data); // 发送数据到Web Worker worker.onmessage = function(e) { console.log('Message received from worker', e.data); }
检查内存泄漏
内存泄漏会导致性能问题,你可以在Chrome DevTools的Memory面板中检查和分析内存使用情况。
使用堆快照
捕获前后的堆快照,比较两者的内存差异,找出潜在的内存泄漏。
定期Profile代码
将性能测试作为常规开发的一部分,不断监控与优化。
通过上述步骤,你可以系统地分析和优化长时间执行的JavaScript代码,提高应用的响应速度和用户体验。
兼容性问题
浏览器兼容性问题通常表现为在不同浏览器下代码表现不一致。需要测试多个浏览器,并使用 Polyfill、CSS 前缀等技术解决
- 分析常见问题
-
图片格式和加载问题
问题: 不同浏览器对某些图片格式的支持不一致(如WebP格式)。
解决方案: 提供多种格式的图片备用方案。 使用服务端检测和处理图片格式,或JS库进行图片格式的检测和切换。
JavaScript API 的兼容性
问题: 不同浏览器对某些新的JavaScript API的支持不一致,如fetch(), promises等。
解决方案: 使用Polyfill填补API。例如,使用Babel编译现代JS代码,并使用polyfill服务(如polyfill.io)加载缺失的API。 使用库包装API(如Axios替代fetch)。
字体和图标的兼容性
问题: 不同浏览器对自定义字体和图标字体的渲染和加载方式不同,导致显示差异。
解决方案: 确保字体文件格式全面(.woff, .woff2, .ttf, .eot, .svg))。 使用Font-face声明中的跨浏览器优化技术。
CSS样式不一致
问题: 不同浏览器对CSS属性的支持和解释可能有所不同。
解决方案: 使用CSS Reset或Normalize.css重置默认样式。 使用前缀自动添加工具,如Autoprefixer。 避免使用浏览器特定的CSS属性。
npm未锁版本,可能导致发布时升级小版本,小版本有bug导致,不容易发现。
- 对比线上正常运行的yarn.lock版本
- 通过二分法查看出问题的版本
- 查看npm文档的ChangeLog.md
问题上升
解决不了的问题,请考虑把问题向上反馈,首先反馈到应用负责人,应用负责人依然解决不了,反馈到梦华
解决问题
已经发现并确认问题原因,解决起来就比较快了
服务端问题
当确定问题源自服务端时,需要与后端开发团队协作解决。
- API接口问题
- 确认前端调用参数和数据格式正确,回归可能影响的范围,验证。
前端代码逻辑问题
目的:修复问题时不影响其他功能
方案:
- 代码修改
- 根据分析结果,针对性地修改代码,并确保新的逻辑更加稳健。
- 集成测试
- 进行端到端测试,确保修复后的代码在整个应用流程中正常工作。
- 使用 Cypress 等工具编写集成测试用例,模拟用户操作和业务流程。
- code review
- 找项目负责人CR,说明问题原因以及解决思路,通过后方可发布
自有库问题
- 代码修改(同上)
- 单元测试
- 编写或更新单元测试,验证修改后的代码逻辑是否正确无误。
- 使用 Jest 等测试框架编写全面的测试用例,覆盖关键逻辑和边界情况。
- 集成测试(同上)
- 版本号管理
- 根据修改的性质,确定版本号的变更方式(如遵循 SemVer 规范)。
- 修复问题: 增加 PATCH 版本号,例如从 1.0.0 增加到 1.0.1。
- 添加新功能但不破坏现有功能: 增加 MINOR 版本号,例如从 1.0.0 增加到 1.1.0。
- 重大变更或破坏性修改: 增加 MAJOR 版本号,例如从 1.0.0 增加到 2.0.0。
- code review(同上)
第三方库问题
三方库一般比较稳定,多查看issue,确认可实施版本。
确认与重现问题
版本锁定
确认你使用的第三方库版本,并检查 package.json 中是否正确锁定了版本。
"dependencies": {
"third-party-lib": "1.2.3"
}
最小可重现示例
创建一个最小可重现示例项目,确认问题是否存在于特定版本的库中。
官网和文档
查看第三方库的官方文档,查看是否有已知问题的相关信息。
检查社区资源
GitHub Issues 页面
访问第三方库的 GitHub 仓库,查看 Issues 页面,确认是否有其他用户报告了相同问题。
提交问题
如果确认是库的问题,可以在 GitHub 上提交一个新的 Issue,把具体的问题说明、重现步骤和环境信息提供给维护者。
尝试解决与替代方案
升级库
尝试升级到第三方库的最新版本,可能已经修复了问题。
降级库
如果升级不能解决问题,尝试降级到以前的稳定版本。
代码临时修复
fork代码
使用替代库
如果问题长期无法解决或维护不善,可以评估并使用功能类似的替代库。
复杂的问题请整理落入文档
详细记录每一步的诊断和解决过程,包括遇到的困难和解决方案。
将常见问题和解决方法加入团队的知识库,帮助团队其他成员快速响应类似问题。