V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
billlee
V2EX  ›  Node.js

用 request 包发了几大波请求,然后它好像阻塞了,可能是什么原因

  •  
  •   billlee · 2016-06-17 21:37:01 +08:00 · 3066 次点击
    这是一个创建于 3064 天前的主题,其中的信息可能已经有所发展或是发生改变。

    概述

    其实不是阻塞,但不知道怎么用一句话描述,具体现象后面有详细讲。

    用的是 request. 伪代码如下

    
    let count = 100;
    
    function batch() {
      // 从数据库用 SELECT ... LIMIT 100 取出 100 条 url
      for (let url in urlList) {
        const req = request(...);
        req.on('error', () => {
          // 一些其它操作
          count--;
          if (count === 0) {
            count = 100;
            batch();
          }
        });
        req.on('end', () => {
          // 一些其它操作
          count--;
          if (count === 0) {
            count = 100;
            batch();
          }
        });
      }
    

    第一波发出去的请求是正常的,过了几波后,在创建完 request, 控制权交还给事件循环时, 要等好长时间才会开始发请求,这个等待的时间会越来越久。试过调整连接池,但只能缓解,不能解决。

    大家有没有碰到过类似的问题?或者有没有排查问题的思路?

    等待发请求时的具体现象

    • 通过打印日志,确定:
      • 计数器工作正常
      • 创建 request 对象的那个循环已经执行完了
    • 但是
      • lsof 看到没有创建任何 tcp 连接(前面的数据库连接除外)。
      • 没有任何 request 的调试日志输出
      • 用 gdb backtrace node 进程,看到几个线程是阻塞在 poll 上,其余几个线程是阻塞在信号量上
    • 等待一段时间后
      • 出现 request 的调试日志输出, lsof 看到 tcp 连接
      • 这个等待时间会越来越久
    3 条回复    2016-06-17 22:24:33 +08:00
    magicdawn
        1
    magicdawn  
       2016-06-17 21:56:09 +08:00
    batch 里的循环没有引用 count, 在 error/end 修改 end 有什么用...
    你这样一下创建了 n 多请求, 会导致系统打开的 fd 急剧增加...

    如果你是使用 callback 的话可以使用 async.parallelLimit, see https://github.com/caolan/async#paralleltasks-callback
    promise, co, 或者 async/await 可以使用 promise.map 控制下并发, see https://github.com/magicdawn/promise.map
    magicdawn
        2
    magicdawn  
       2016-06-17 21:57:30 +08:00
    > 在 error/end 修改 end 有什么用...

    在 error/end 修改 count 有什么用...
    billlee
        3
    billlee  
    OP
       2016-06-17 22:24:33 +08:00
    @magicdawn 我的目的就是并发很多请求,因为这些 url 大部分是无法访问的。
    修改 count 这个先不管吧,这是伪代码(公司政策不允许外发代码),实际代码这里肯定是没问题的,因为打印的日志显示计数从 100 降到 0 了,并且 batch 也已经被调用了。

    async.parallel 看起来不错,下周我去换上。不过这个应该不是关键问题吧,我这也相当于是自己实现了 async.parallel 的功能。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5385 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 07:39 · PVG 15:39 · LAX 23:39 · JFK 02:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.