开发环境前端:Vue2.0后台:NodeExpress浏览器:Chrome部署系统:Linux问题现象在已有项目的基础上增加了两个页面,但是在使用过程中发现,连续操作几次的时候之后,页面会变得异常缓慢。查看接口调用,发现接口请求长时间处于pending状态,但等待1-2分钟左右接口仍会返回响应结果。如下图:原因分析通过反复复现问题(切换不同页面,触发请求),发现了一个规律,就是每切换到第7页,所有接口都会被屏蔽。1分多钟后返回。看看这1分钟左右的时间都花在哪里了?从上图可以看出,整个接口请求的大部分时间都花在了Stalled阶段。现在的问题是Stalled是什么意思?下面是一个比较简单的解释:请求发送前等待的时间。此时间包括代理协商中花费的任何时间。此外,此时间将包括浏览器等待已建立的连接变为可用以供重用的时间,遵守Chrome的每个源规则最多六个TCP连接。根据上面的解释,可能有两种原因:TCP连接有问题,无法成功建立链接;TCP连接正常,但已被占用,无法使用。先看第一个问题,TCP连接是否正常?$lsof-i:8700COMMANDPIDUSERFDTYPEDEVICESIZE/OFFNODENAMEnode26315mumingv12uIPv44492151450t64TCP*:8700(LISTEN)node26315mumingv16uIPv44492175690t64TCPlocalhost:8700->174LIABSH:174.264:174.26EDnode26315mumingv17uIPv44492175700t64TCPlocalhost:8700->172.24.186.14:54065(ESTABLISHED)node26315mumingv18uIPv44492175800t64TCPlocalhost:8700->172.24.186.14:54066(ESTABLISHED)node26315mumingv19uIPv44492175810t64TCPlocalhost:8700->172.24.186.14:54067(ESTABLISHED)node26315mumingv20uIPv44492268740t64TCPlocalhost:8700->172.24.186.14:54574(ESTABLISHED)node26315mumingv21uIPv44492175830t64TCPlocalhost:8700->172.24.186.14:54069(ESTABLISHED)上图中8700是网站的服务端口号,172.24.184.14是Chrome浏览器所在Mac的IP。在重现问题的过程中,我一直执行lsof-i:8700持续观察,发现当第7次切换页面时,这里的TCP连接数不再增加,维持在6左右并且状态为ESTABLISHED(已经建立)。所以基本可以排除TCP连接的问题。当然你也可以通过netstat命令查询TCP连接状态。$netstat-tunpa|grep8700(无法识别所有进程,不会显示非拥有的进程信息,您必须是root才能看到全部。)tcp000.0.0.0:87000.0.0.0:*LISTEN27765/nodetcp0010.95.199.140:8700172.24.186.14:65413ESTABLISHED27765/nodetcp0010.95.199.140:8700172.24.186.14:65412ESTABLISHED27765/nodetcp0010.95.199.140:8700172.24.186.14:65421ESTABLISHED27765/nodetcp0010.95.199.140:8700172.24.186.14:65420ESTABLISHED27765/nodetcp0010.95.199.140:8700172.24.186.14:65419ESTABLISHED27765/nodetcp0010.95.199.140:8700172.24.186.14:65422ESTABLISHED27765/node我们再来看第二个问题,谁占用了TCP连接不释放?查看是否有其他请求占用这些TCP连接,检查所有请求,如果没有当然:原来每次切换页面,浏览器默认都会发送请求获取一个网页图标。这不是前端业务逻辑主动调用的XHR请求,也是对后端的GET请求。其实如果没有要求显示具体的网页图标的话,后台简单的返回一个消息就可以了,不需要准备网页图标。如果浏览器无法获取图标,它将显示一个默认图标。问题找到了,就看后端为什么不返回图标,解决。具体针对本项目,nodeexpress的app.js入口文件中并没有注册相应的处理逻辑。//接口路由loadRouter(app,'/project-name',path.join(__dirname,'app/controllers'));//静态页面app.use('/project-name',express.static(path.加入(__dirname,“webroot”,“项目名称”)));//favicon.ico和其他不支持的请求app.get("*",function(req,res){if(req.path==="/favicon.ico"){return;//!!!你可以'这里不能直接返回,需要返回具体内容,否则会阻塞express框架返回响应信息!!!}thrownewPathError();});知道问题后,修改就很简单了。app.get("*",function(req,res){if(req.path==="/favicon.ico"){res.json({'status':0,msg:''});//这里只返回任何内容,不影响浏览器使用默认图标显示}thrownewPathError();});至此,问题就解决了。FAQQ:为什么浏览器和服务器最多只能建立6个TCP连接?TCP连接资源的数量是有限的。如果不限制数量,如果所有TCP都被占用,系统将“无法提供服务”。一般浏览器的TCP并发连接数在5、6个左右,Chrome是6个。至于为什么有这么多,这是各个浏览器自己设定的,没有标准。具体解释参考:官方文档。Q:以后出现此类接口问题如何解决?一般按照以下步骤检查:浏览器端查看XHR请求,判断XHR请求本身是否异常;浏览器端查看ALL请求判断非XHR请求是否异常;服务器端检查服务本身是否正常;服务器端检查服务建立的TCP连接是否正常;抓包检查TCP交互和业务请求交互报文是否有异常。参考NetworkIssuesGuideUnderstandingResourceTiming对chrome时间线停滞问题的分析
