情景再现

近期发现网站访问变慢,经常会出现请求无法响应的问题,一个请求长时间没有返回,导致页面出现504(Gateway Timeout),我们使用的nodejs+ngnix(反向代理)。

猜测原因

  服务器内存使用过高,导致服务器处理缓慢?

  并发请求过多导致请求缓慢?

...

定位问题

  查看服务器cpu和内存使用情况:发现服务器的cpu空闲率为95%左右,内存使用率在40%~60%。会不是内存使用过高导致的呢?我们重启了nodejs服务,此时我们观察到内存使用率有所减少在20%~40%左右,结果并没有什么用,访问依旧很慢。

  是不是请求数过多导致的呢?查看服务器日志,发现每分钟的请求量级并没有特别高,应该不是这个问题。

  因为我们使用了nginx反向代理,就像看看是不是nginx服务器的配置问题。经过抓包查看,发现部分请求的时间有几十毫秒还有几十秒的,当达到60秒的时候,服务器出现504错误。(proxy_connect_timeout,proxy_read_timeout,proxy_send_timeout,在nginx中,这些的默认配置是60s,所以一旦请求超过一分钟没有响应,服务器就直接返回504)再三检查nginx配置,没有发现能够改变这个问题。

  查看nodejs服务,检查是否我们代码层的逻辑导致服务器没有响应,触发nginx的超时。经过对代码的测试,发现我们有一个发布上线的逻辑比较耗时,大概时间为5到6秒钟,这个过程需要依赖第三方的服务,所以处理时间长度过长,在用户发送请求时,部分用户需要经历这个过程。此时,访问其他页面的时候,就会出现这种情况。我们的做法是,将发布上线的逻辑,只在编辑的时候使用。普通用户访问的时候,使用上线生成的线上文件。你们一定觉得这样问题就可以解决了,其实这是一个导火索,与另外的一个问题同时导致了线上的pedding问题。

  上面这个问题解决之后,发现向上并没有任何太大的改观。同时发现还有一个请求,依赖其他的服务器,那就是数据库请求。我们重新审查了一下什么原因导致数据库查询请求过慢。我们查看了我们所有的数据库慢查询,发现一个共性,这些慢查询的表数据量都很大,同时我们并没有对这些表建立索引,导致查询很慢。经过简单的本地测试:设置过索引的查询,在一个几十万条数据的表中,查询时间1ms以内;未设置索引的情况下,同一个查询语句需要的时间是200ms左右,结果令人差异,竟然差距这么大。我们对线上的数据库表根据查询需求,设置了索引,结果得到了很大的改观,访问速度有了显著的提高,基本上很快就有了响应。

  此时,线上的问题得到了初步的解决。

思考

  通过上面的探索我们发现,一般出现一个请求pedding或者是504的情况,是因为服务器处理的太慢,无法快速响应,如果服务器再不能并发处理的话,可能就会出现这种情况,所以我们需要优化我们服务端处理的速度。

  针对这种情况,优化我们线上的逻辑:

  优化建表逻辑:考虑主键、外键、索引等情况,优化数据库请求

  优化服务端逻辑:优化发布上线逻辑,不过度依赖第三方服务,如果需要依赖的话,尽量采用子进程完成,不影响主进程的响应;与此同时,完成多服务器同步问题,不需要用户在访问时,再进行生成,导致请求阻塞。

  其他性能优化:资源静态化,资源加载等等问题

参考资料:
https://nodejs.org/api/http.html#http_class_http_agent
http://melon.github.io/blog/2014/12/08/nodejs-agent-and-size-limit-of-get-method/

记一次pending请求问题查找过程的更多相关文章

  1. 在浏览器中简单输入一个网址,解密其后发生的一切(http请求的详细过程)

    在浏览器中简单输入一个网址,解密其后发生的一切(http请求的详细过程) 原文链接:http://www.360doc.com/content/14/1117/10/16948208_42571794 ...

  2. 一个http请求的详细过程

    一个http请求的详细过程 我们来看当我们在浏览器输入http://www.mycompany.com:8080/mydir/index.html,幕后所发生的一切. 首先http是一个应用层的协议, ...

  3. HTTP请求响应的过程

    1. TCP/IP协议分层结构 应用层(含括了OSI七层中的上三层,分别为应用层,表示层, 会话层):DNS,  URI,  HTML,  HTTP,  TLS/SSL,  SMTP,   POP,  ...

  4. 记一次mysql请求超时甩锅历程

    今天下午业务找我说是线上环境一个mysql库很慢,请求出现了大量的超时,让帮忙看看,以下为查找过程及甩锅过程. 1. mysql请求超时,ok,我们所有线上mysql都是开启了慢查询日志的,查找慢查询 ...

  5. Asp.net MVC进入请求管道的过程

    Asp.net MVC进入请求管道的过程 Asp.Net MVC 跟AspNet 入口解释 Asp.Net MVC请求处理过程 mvc 请求模型 mvc的原理 mvc模型 NewMVCPipleLin ...

  6. php中include包含文件路径查找过程

    首先,“路径”分为三种: 1.绝对路径,以/开头(unix系统)或c:等盘符开头(windows系统). 2.相对路径,以.开头,有./(当前目录)和../(上级目录). 3.其他路径,不是绝对路径和 ...

  7. AJAX异步请求原理和过程

    AJAX 指异步 JavaScript 及 XML(Asynchronous JavaScript And XML),它不是一种新的编程语言,而是一种使用现有标准的新方法. AJAX 基于 JavaS ...

  8. HiPAC高性能规则匹配算法之查找过程

    收到一封邮件,有位朋友认为我误解了nf-HiPAC.如此的一个高性能算法怎能被什么传统的hash,tree之类的胁迫.是啊.HiPAC是一个非常猛的算法.文档也比較少,这就更加添加了其神奇感,可是这决 ...

  9. Spring MVC 原理探秘 - 一个请求的旅行过程

    1.简介 在前面的文章中,我较为详细的分析了 Spring IOC 和 AOP 部分的源码,并写成了文章.为了让我的 Spring 源码分析系列文章更为丰富一些,所以从本篇文章开始,我将来向大家介绍一 ...

随机推荐

  1. 怎样在 SSASserver之间做同步

     简单介绍: 从SQL Server 2005開始,分析服务就支持了同步的功能.本文将介绍怎样在SQL Server 2012下同步Adventureworks的分析服务数据库.通过同步的功能,我 ...

  2. Java实现BASE64编解码

    Java实现BASE64编解码 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs BASE64和其它类似的编码算法通经常使用于转换二进制数据为文本数据,其目 ...

  3. [转] 关于SIGPIPE导致的程序退出

    PS: 如果服务器程序不忽略SIGPIPE,在某些时候TCP writer收到这个信号,会导致进程退出 The rule that applies is: When a process writes ...

  4. Linux crontab命令

    --常用参数:crontab -l               //查看当前用户下的cron任务crontab -e               //编辑当前用户的定时任务crontab -u  jo ...

  5. iis7 发布mvc 遇到的HTTP错误 403.14-Forbidden Web 服务器被配置为不列出此目录的内容

    iis 7上发布mvc报错:403.14-Forbidden Web 服务器被配置为不列出此目录的内容 提示里面的解决方法是: 如果不希望启用目录浏览,请确保配置了默认文档并且该文件存在. 使用 II ...

  6. css3 3D变换和动画

    3D变换和动画 建立3D空间,transform-style: preserve-3d perspective: 100px; 景深 perspective-origin:center center ...

  7. SQL Server 2005、SQL Server 2008版本比较

    SQL Server 2005的版本有SQL Server 2005企业版(Enterprise).SQL Server 2005标准版(Standard) 和SQL Server 2005工作组版( ...

  8. java 自定义注解以及获得注解的值

    1.自定义注解 import java.lang.annotation.*; @Documented @Target(ElementType.FIELD) @Inherited @Retention( ...

  9. JavaScript Arguments 实现可变参数的函数,以及函数的递归调用

    //可变参数的函数 注:也可以使用对象作为参数来实现 function Max() { var temp = arguments[0] || 0; for (var i = 1; i < arg ...

  10. void *memmove( void* dest, const void* src, size_t count );数据拷贝,不需要CPU帮助

    分享到 腾讯微博 QQ空间 新浪微博 人人网 朋友网 memmove 编辑词条 编辑词条 -->   memmove用于从src拷贝count个字符到dest,如果目标区域和源区域有重叠的话,m ...