背景

最近在提供后台API时,提供了一个简单逻辑的接口

部署在测试环境,自测没问题,提交测试

突然有一天,接口响应延迟严重,几乎每次都是3-4秒返回

这对于一个接口来说,肯定是有问题的

于是便有了以下的方法尝试

重启FPM

  • 最开始以为不是什么大问题,猜想可能是fpm问题

    毕竟测试环境,部署代码繁多
  • 重启后,接口响应正常,可不一会就又复现

重新分析定位问题

  • 经过几次的尝试后,发现问题其实没有那么简单
  • 重启fpm后,过了不到几秒,问题依然复现
  • 编写简单的php文件,无复杂逻辑,只输出字符串,问题复现
  • 命令行执行文件,无此问题
  • 经过以上尝试,确认是FPM的问题

    或者PHP的初始化解析执行的问题,当时想是不是有特定的模块加载

    经过php -m 查看,无特殊模块(其实应该仔细看看,所以才绕了弯路)

日志定位

有了上面的分析,最先想到的是利用日志查看问题

查看nginx日志

  1. nginx 日志 格式,添加详细的 各个时间段的相应
  2. log_format main '$remote_addr [$host] - $remote_user [$time_local] $request upstream_response_time: $upstream_response_time
  3. request_time: $request_time upstream_connect_time: $upstream_connect_time upstream_header_time:$upstream_header_time
  4. $status $body_bytes_sent $http_referer $http_user_agent ';
  5. 添加了
  6. upstream_response_time
  7. upstream_connect_time
  8. upstream_header_time
  9. 含义如下:
  10. request_time
  11. nginx服务,从发起请求的客户端获取到第一个字节开始,到返回给客户端最后一个字节,日志写入文件后,所经过的时间。单位为秒。
  12. upstream_connect_time
  13. nginx服务,从与上游服务开始建立连接,到连接建立成功,所经过的时间。单位为秒。
  14. upstream_header_time
  15. nginx服务,从与上游服务开始建立连接,到接收到响应返回头的第一个字节,所经过的时间。单位为秒。
  16. upstream_response_time
  17. nginx服务,从与上游服务开始建立连接,到接收完响应返回的最后一个字节,所经过的时间。单位为秒
  18. ![](https://img2020.cnblogs.com/blog/385704/202007/385704-20200728162028181-1944819290.jpg
  19. [参考链接](https://juejin.im/post/5d26eb16f265da1bd522f8d6)
  20. 程序真正的运行时间 = $upstream_header_time - $upstream_connect_time
  21. $request_time 中包含了数据返回时间
  22. $request_time 中包含了日志打印的时间
  23. nginx 日志显示
  24. xxx [xxx] - - [11/Jul/2020:13:36:45 +0000] POST /xxx/xxx HTTP/1.1 upstream_response_time: 3.048 request_time: 3.048 upstream_connect_time: 0.000 upstream_header_time:3.048 200 98 - Dalvik/2.1.0 (Linux; U; Android 8.1.0; vivo 1808 Build/O11019)
  25. 从中可以看出确实是 上游服务FPM 返回延迟了

配置 FPM 慢日志

lowlog = /xxx/www-slow.log request_slowlog_timeout = 1s

发现 慢日志中,并没有记录

于是怀疑是否 日志文件权限有问题,修改后依然未写入

想到用sleep的方式,写入慢日志,成功写入

现象就是 配置了1秒的FPM慢日志,接口响应超过1s,但没有写入慢日志

那就说明 PHP 程序执行完成后,又做了什么处理,导致了延迟

或者 其他的配置问题

文件描述符

网上搜索, 可能是 文件的打开数量有限制, 并没有做优化

于是 查看对应的配置

nginx 配置文件 worker_rlimit_nofile

ulimit -n

是做了优化的的

也并不是网上所说的问题

思考

  • 所有的PHP程序响应都有延迟,超过3s左右

    所以并不是个例,和其他的如mysql redis 连接没关系
  • 突然间出现的,原来是没问题的,应该是近期做了更改

    但由于测试环境,东西太多,一时也找不到是什么改动
  • 命令行模式下,没有延迟,所以和FPM有关

    而重复FPM后,几秒内正常,后又复现

    一直以为是FPM配置有什么问题,目前看并不是
  • 所以肯定是 程序处理完成后,又做了什么,导致了延迟

    那有什么办法可以追踪代码的执行吗

    对于php而言,xhprof扩展 是可以很好的展示一个流程中的耗时

    而且还有对应的图片展示(需要安装扩展),但还需要安装

    于是就有了下面的方法

strace调试跟踪

简单来说,strace是用来跟踪进程内的系统调用和接受的信号。

对程序调试很有帮助

  • 于是,来调试FPM的进程,看看都做了哪些调用

    strace -t -f $(pidof php-fpm| sed 's/\([0-9]*\)/\-p \1/g') -epoll -o /tmp/strace.txt

    打开文件

    12406 06:55:13 poll([{fd=5, events=POLLIN}], 1, 5000) = 1 ([{fd=5, revents=POLLIN}])

    12406 06:55:13 poll([{fd=6, events=POLLOUT|POLLWRNORM}], 1, 10000) = 1 ([{fd=6, revents=POLLOUT|POLLWRNORM|POLLERR|POLLHUP}])

    12405 06:55:16 --- SIGQUIT {si_signo=SIGQUIT, si_code=SI_USER, si_pid=12401, si_uid=0} ---

    12405 06:55:16 +++ exited with 0 +++

    12401 06:55:16 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12405, si_status=0, si_utime=0, si_stime=0} ---`
  • 通过以上信息,在 06:55:13后,确实有超过3秒的时间,是 fd=6 导致的, 那 fd=6 是什么

    可通过 lsof -p pid 的方式查看

    但 进程id 12405 退出了

    就是说,由于FPM的动态启动进程的配置,一个进程退出后,会重新生成进程,已达到配置的进程数

    所以 一边打印调试信息,一边输出 工作pid的 文件信息
  • lsof -p 12408

    php-fpm 12408 apache 5u IPv4 1203792101 0t0 TCP localhost:cslistener->localhost:22384 (ESTABLISHED)

    php-fpm 12408 apache 6u IPv4 1203794606 0t0 TCP xx.com:28866->ip-10-66-100-169.ec2.internal:9411 (SYN_SENT)

此时,原因终于找到了,在每次结束后,又请求了某个ip 9411端口的服务

可以看到tcp状态是 SYN_SENT,虽然已发出连接请求,但对应没回应,并不是ESTABLISHED状态

说明是对应请求机器的问题

于是去查看此ip对应机器,原来确实有此机器,但不知什么时候起,此机器已下架了

导致了这个问题,此刻想到了为什么突然之间接口就有延迟了

问题修复

既然确认了是连接了某个服务导致的问题,对应的php配置文件应该有配置

于是 找到 所有模块配置文件ini路径,搜索ip

发现是 其 molten 扩展配置

molten 扩展是一个全链路追踪的工具

molten追踪php核心调用库运行时信息并且按照zipkin/optracing格式输出信息。

可以追踪curl,pdo,mysqli,redis,mongodb,memcached 这么多的运行信息。

去掉此扩展加载,重启FPM后,接口响应正常

总结

  • 问题出现的时候,最直观的方式应该是日志,通过查看日志,可以解决大部分问题
  • 当日志解决不了的问题,如何调试,就成了问题解决的关键

    strace ltrace 以及 gdb 调试

API返回延迟,FPM重启后恢复之后又重现 问题解决方案的更多相关文章

  1. 每天一个linux命令:ifconfig命令 临时修改重启后恢复原样

    许多windows非常熟悉ipconfig命令行工具,它被用来获取网络接口配置信息并对此进行修改.Linux系统拥有一个类似的工具,也就是ifconfig(interfaces config).通常需 ...

  2. redis集群节点重启后恢复

    服务器重启后,集群报错: [root@SHH-HQ-NHS11S nhsuser]# redis-cli -c -h ip -p 7000ip:7000> set cc dd(error) CL ...

  3. CentOS7重启后resolv.conf被重置的解决方案

    近期在修改一台CentOS7服务器的dns时发现只要重启服务器DNS就会被强制还原,解决方案如下: 1.首先在网卡设置中修改NM_CONTROLLED的值: 修改文件/etc/sysconfig/ne ...

  4. 如何保证修改resolv.conf后重启不恢复?

    如何保证修改resolv.conf后重启不恢复? 修改/etc/resolv.conf,重启网卡后,/etc/resolv.conf恢复到原来的状态. CentOS.redhat下面直接修改/etc/ ...

  5. 分享:Windows2008重启后提示系统恢复选项的解决办法

    如题:WINdows2008服务器. 重启后提示系统恢复选项的解决办法 使用windows 2008后,不能启动的问题,重启后出现 修复系统选项 采用下面帖子中的部分命令搞定之. 我自己是直接使用:选 ...

  6. ubuntu网络重启后或主机重启后,/etc/resolv.conf恢复原样的解决办法

    ubuntu网络重启后或主机重启后,/etc/resolv.conf恢复原样的解决办法 /etc/resolv.conf中设置dns之后每次重启该文件会被覆盖,针对这种情况找了一些个解决方法 防止/e ...

  7. koa中返回404并且刷新后才正常的解决方案

    概述 这几天学习koa2,有一些心得,记录下来,供以后开发时参考,相信对其他人也有用. 起因 这几天学习koa2,写的代码执行时有一个奇怪的bug:明明能够返回数据,却有时正常返回数据,有时偏偏给你返 ...

  8. Hyper-V 激活Windows系统重启后黑屏的解决方法 + 激活方法

    异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 服务器相关的知识点:http://www.cnblogs.com/dunitia ...

  9. web Api 返回json 的两种方式

    web api写api接口时默认返回的是把你的对象序列化后以XML形式返回,那么怎样才能让其返回为json呢,下面就介绍两种方法: 方法一:(改配置法) 找到Global.asax文件,在Applic ...

随机推荐

  1. 【树形dp】 Bzoj 4472 Salesman

    题目 某售货员小T要到若干城镇去推销商品,由于该地区是交通不便的山区,任意两个城镇 之间都只有唯一的可能经过其它城镇的路线. 小T 可以准确地估计出在每个城镇停留的净收 益.这些净收益可能是负数,即推 ...

  2. LINUX 下 一些常用的信息显示命令:

    tcsh——shell程序,它可以在登录shell和shell 脚本命令处理器之间做命令语言解释器.stat——显示指定文件的相关信息who.w——显示在线登陆用户whoami——显示用户自己的身份h ...

  3. 【python爬虫实战】使用Selenium webdriver采集山东招考数据

    目录 1.目标 2.Selenium webdriver说明 2.1 为什么使用webdriver 2.2 webdriver支持浏览器 2.3 配置与使用说明 3.采集 3.1 分析网站 3.2 遍 ...

  4. (私人收藏)[开发必备]最全Java离线快速查找手册(可查询可学习,带实例)

    (私人收藏)[开发必备]最全Java离线快速查找手册(可查询可学习,带实例) https://pan.baidu.com/s/1L54VuFwCdKVnQGVc8vD1TQnwmj java手册 Ja ...

  5. 学习 Java 网站推荐给你

    推荐几个非常不错的 Java 学习网站 LearnJava 在线 这是一个非常不错的学习 Java 的在线网站,纯免费.这是一个个人项目,旨在通过简单有效的在浏览器中进行练习让你快速掌握 Java 编 ...

  6. ASP.NET CORE MVC用时分析工具MiniProfiler

    ASP.NET CORE MVC用时分析工具MiniProfiler MiniProfiler(https://miniprofiler.com/)是一个轻量级且简单易用的分析工具库,它可以用来分析A ...

  7. HDFS读写流程(重点)

    @ 目录 一.写数据流程 举例: 二.异常写流程 读数据流程 一.写数据流程 ①服务端启动HDFS中的NN和DN进程 ②客户端创建一个分布式文件系统客户端,由客户端向NN发送请求,请求上传文件 ③NN ...

  8. Java入门系列之重写

    前言 关于所有Java系列文章面向有一定基础的童鞋,所写每一篇希望有一定含金量,有些内容可能会从Java整个语法全局考虑穿插后续要讲解的内容以成系统,若不理解,请看完后再学习.上一节我们讲解完了fin ...

  9. 数据可视化之powerBI基础(一) 如何查看PowerBI图表背后的数据

    https://zhuanlan.zhihu.com/p/64405494 图表很直观,但有时候我们不仅想看图,也想更进一步查看生成该图表的明细数据,在PowerBI中有三种方式. (一)在图表上单击 ...

  10. 使用位运算、值交换等方式反转java字符串-共四种方法

    在本文中,我们将向您展示几种在Java中将String类型的字符串字母倒序的几种方法. StringBuilder(str).reverse() char[]循环与值交换 byte循环与值交换 apa ...