lovecn / lovecn.github.io

个人记录
5 stars 5 forks source link

当你的程序(PHP,C/C++,Java,Python,Go等等)出错了,网络请求失败了,如何调试和定位? -- twin #9

Open mingyun opened 10 years ago

mingyun commented 10 years ago
  1. 断点,error log. -- 零度西瓜
  2. 网络请求失败,比如404,500,cannot resolve host, 返回数据格式不正确等等 -- twin
  3. 分析程序日志,系统日志,各种系统网络路由器监控日志,再结合机房的配合 基本能搞定 -- Mandman
  4. 一步步定位,看是哪个环节出错,把php的error_reporting打开,fpm日志打开,nginx日志打开,tcpdump抓包看是否正常请求和到达 -- 星星
  5. 调试一个请求:b/s 用浏览器的network,如果有302的话可选择preserve log 或者用插件stop掉302;b/s的话可以tail -f查access.log 如需更详尽的请求信息可以用抓包工具fiddler、Charles 等。拿到请求后可在命令行下做调试(chrome 可以在networks右键得到curl)。高效率依赖于好工具,比如灵活使用用管道,查看json的话用:curl url | php -r 'var_dump(json_decode(file_get_contents("php://stdin"))); 还有更强大的jq: curl url | jq 。如果需要直接编辑可以用vim:curl curl | vim - 。而代码调试中经常用到二分打印,或者二分法分断删除再执行。 -- hilojack
  6. wireshark抓包分析 -- 杨锡坤
  7. if(isset($_GET['debug'])) register_shutdown_function(function(){ var_dump(error_get_last()); }); //加在头部 无需修改任何配置 对程序无害 绿色 -- 吴子棋
  8. PHP firebug也不错啊 或者直接封装好函数输出<!—— print_r($var) ——> 查看源码 -- weizhao
  9. 先判断是否是网络故障了, ping 不同ip, dig 不同域名或路由, 检查防火墙, curl 测试不同链接, 如果不是网络问题, 就要看网络请求失败的具体header status, 是否404,301,302, 或500, 如果500, 则基本可以断定是对方服务问题, 比如请求某接口, 超过频率限制, 或对方服务已挂 -- 老李
  10. ping, telnet, dig, route, traceroute, iptables, curl, 基本上可以确定问题了 -- 老李
  11. 开发要掌握dns的原理, 为啥/etc/hosts 可以绑定域名, /etc/resolv.conf用来干啥, 主要理解dns是怎样工作的 -- 老李
  12. 如果linux防火墙端口没开,talent是不是也会通? 答: 恩 -- 老
  13. 用户说你的网站打开太慢,请列出所有可能性,以及排查方法

一、网络问题

1、临时性
     检查:ping, mtr 等命令,检查网络状况,DNS等
     解决:联系机房或视具体情况而定

2、网络不同或距离太远
     检查:客户端和机房所在网络情况
     解决:双线机房或分布式部署,动态DNS,需要考虑成本

 3、资源加载慢
      检查:chrome控制台
      解决:CDN,合并请求,压缩页面代码等

二、前端问题

 1、浏览器太烂

 2、页面设计不佳
      检查:浏览器解析时间,是否DOM节点过多,JS有问题等
      解决:优化页面代码

三、服务端问题

1、服务器状态
      检查:负载,CPU, 网络,内存,磁盘空间等使用情况
      如果单台服务器性能受限,考虑调整为分布式架构,如nginx转发,DB分库分表等

 2、PHP响应慢
      检查webserver日志中的响应时间
      如果服务器整体负载不高,但PHP的数据返回时间过长,在PHP代码中分段输出处理时间
      更具环境的不同,可以选择直接输出或是写入日志
      如果是高访问量的在线调试,一般选取一定比例记录日志,防止日志过多带来的额外系统开销
      逐步缩小范围,定位、优化

 3、DB响应慢
      有分为读取慢和写入慢

      读取慢
      检查:慢查询日志;
                show processlist 查看当前DB状态,看哪些请求停留较多
                top查看mysql进程的开销
                代码中记录SQL和执行时间
      解决:
                手动执行可疑SQL(注意排除query cache的影响),用explain,profile等工具分析SQL性能
                再考虑是否优化索引,或者分库分表,或者增加缓存

      写入慢
      检查:除读取慢的检查方法外,还有
                iostat 检查磁盘IO
                查看mysql binlog的写入速率
      解决:增加缓存,分库分表,优化索引,从业务逻辑上考虑减少DB操作,合并写入

 4、其他
      被攻击,webserver进程数受限,甚至内网流量过高等原因,都有可能导致访问缓慢,具体情况具体分析

-- XiangZ

  1. 大家说了网络层面的,我说一下应用层面的吧,对于后端程序最靠谱的方法是看日志,因此代码里写日志就非常重要了,我这的后端产品都有全局的日志对象,每条日志记录编号、时间、类型、级别、执行经过时间、内容以及SessionID、请求编号、调用顺序号、访问渠道、用户编号、IP地址等标识请求方的字段,一般开发时的日志级别是Debug级别,线上运行时记录的日志级别是Error级别,可以通过配置指定特定的用户、IP地址的日志级别,比如某用户反映操作出错或相应很慢,排除网络问题后可以对该用户开启Debug级别的日志,通过日志定位问题。有两块日志是公共的,一是接口入口,记录接口的响应时间及未接管异常的错误信息、栈信息,二是统一封装的数据库模块记录的SQL执行日志,记录SQL响应时间及出错信息。 -- 水浸街
  2. 问: 线上不开debug有哪些原因呢? 为什么要分两块日志呢?sql出错也可以归到异常的

答: 日志记录本身是要消耗资源的,debug的信息非常多,所以不能开,当然性能允许也可以开。我说的两块日志是公共日志,就是不需要业务模块显式写日志的,实际写还是一个入口的。SQL出错的原因有很多,比如违反唯一性约束,这种情况下还是可控的,称为错误(error)合适一些,而异常则会引起程序流程终止执行,属于更高级别的错误(fault)。

  1. 对sql日志更多的应该还是一个审计,有没有异常,有没有慢sql. 要保障数据库的安全和稳定 -- 易元建
  2. 对,这是另一个功能,这里再次说一下SQL绑定变量,使用绑定变量除了可以提高效率,还可以保证一个系统的SQL语句的数量是有限的,可以从日志统计出各SQL语句的平均耗时,发现有问题的SQL语句 -- 水浸街
  3. 问: sql的error和fatal通过errorno区分? 那业务逻辑不就变复杂了吗?每次都得考虑各种code

答: 写日志不需要通过errorno区分,在入口try-catch捕获异常就可以了。 -- 水浸街

  1. 有个记log的形式叫cross finger。debug类型日志会先放内存里不落地 当出现error以上日志 就会把所有debug(包括之前未记录)也落地。这样可以更了解出错时的情况,减少让用户去重现的次数 -- twin
  2. log+strace+tcpdump+systemtap - 李奇
  3. 出错比请求慢定位方便。取出URL,手动请求,根据返回一点点下去,一般会很容易发现问题在哪。--7 Days
  4. 重点还是要log打的好 — 李秋林
  5. java,机器挂了有报警,业务出错有日志,有专门监控异常的系统定期分析异常原因,自己也有业务api工具线上出问题先看接口是否异常,然后再跟踪日志 — hello,zhuli

附加: 问:命名空间的好处是什么呢? — 李博 答:依赖管理和自动加载在下划线时代就有了 只是没现在这么成熟。 命名空间能做的,下划线基本都能做。 要说好处 我看到的是开源大佬不再顾忌长类名的问题,通过命名空间设计出更优秀合理的架构 symfony doctrine 都是用了命名空间后 类名变长 分层变细的例子 —twin

问:我们还在使用5.2.*这种版本的php。没有跟得很近。大家是否遇到什么强需求,会迫使或说主动使用更高版本的php? — 李博 答:一般也可以不升级,唯一担心就是将来很多开源代码都支持很多新特性,你老版本不能用,就会郁闷哦 — 黑夜路人 答:5.2太老了,PHP优秀的开源类库,大多用上了命名空间,要求最低5.3.3 — twin