Egg: 遇到worker超时的问题,请问如何解决

Created on 23 May 2017  ·  24Comments  ·  Source: eggjs/egg

  • Node Version: 7.9.0
  • Egg Version: 1.1.0
  • Plugin Name:
  • Plugin Version:
  • Platform: centos
  • Mini Showcase Repository:


我在我的schedule里面跑了一个很大的任务,平均消耗时间在两分钟。
然后就频繁看到了这个错误:
2017-05-23 14:44:22,083 ERROR 25143 nodejs.ClusterClientNoResponseError: client no response in 34854ms exceeding maxIdleTime 30000ms, maybe the connection is close on other side.
at Timeout.Leader._heartbeatTimer.setInterval [as _onTimeout] (/opt/dedv/node_modules/cluster-client/lib/leader.js:69:23)
at ontimeout (timers.js:386:14)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
name: 'ClusterClientNoResponseError'
pid: 25143
hostname: server-53

请问有解决的办法吗?
感觉像是有个worker一直在跑,然后就没有响应,master误以为它挂掉了。

Most helpful comment

种棵树,给后人乘凉

const util = require('util');
const exec = util.promisify(require('child_process').exec);

async function lsExample() {
  const { stdout, stderr } = await exec('ls');
  console.log('stdout:', stdout);
  console.log('stderr:', stderr);
}
lsExample();

reference:https://nodejs.org/dist/latest-v10.x/docs/api/child_process.html

All 24 comments

这个很大的任务是同步运行的么?

用了await,应该不算吧。。。里面全是数据库更改操作。

恩,还有其他的日志么?

/cc @gxcsoccer

schedule 不是基于 messenger 的么,为啥和 cluster-client 有关。

就是重复的报这个错。我只要移除了那段schedule里的执行代码,空跑那个schedule,就立马没事了。

刚刚把schedule的任务时间降到了40秒以内。但是还是有这个问题。
现在的频率是30秒跑一次。schedule的任务平均耗时在40秒以内。

抱歉,刚刚看了一下,我强制只用了一个CPU核。是不是这个任务把这个CPU核跑满,然后导致了这个唯一的worker失去了响应?请问能调整心跳的时间吗?

@LiShiSangZi 能否提供一个重现的代码片段?

抱歉,刚刚看了一下,我强制只用了一个CPU核。是不是这个任务把这个CPU核跑满,然后导致了这个唯一的worker失去了响应?请问能调整心跳的时间吗?

如 cpu 密集型,只有一个 js 执行线程,没有任何 io 释放的操作,肯定 worker 就没法发心跳包了。

@gxcsoccer schedule 里面做一个 cpu 循环 40s,应该就能模拟了。

@fengmk2 我的代码里全是数据库的操作。IO应该是会释放的吧。

@gxcsoccer schedule 里面做一个 cpu 循环 40s,应该就能模拟了。

这个我也没办法了

@gxcsoccer 我的代码里全是对数据库的操作。大致就是把一张大表拉出来,计算一下数据,然后再一条一条的update回去。和cpu循环40s,还是有区别的啊。

@LiShiSangZi 你看下处理数据的耗时是多少

总共的时间是40秒,总共数据库的时间,并发的,没法算。
我比较感兴趣的是,全程都是带Promise的数据库请求。这个进程照理说不应该是能够腾出一点点的时间来响应一下心跳么。

@wencheng1990 我们之前是所有的db请求一次性Promise.all触发。现在用await一个一个来,就没有这个问题了。总体执行时间上也差不多。

在大量的循环体里,合理做一下 sleep 就好了,比如:

for (let i = 0; i < list.length; i++) {
      if (i % 100000 === 99999) {
        await this.sleep(0);
      }
      ...
    }

...我也遇到了这个问题,我定时任务在跑一个脚本打包任务,用到了const { spawnSync } = require('child_process'); 然后就报这个错。。。只有一个promise,有什么解决办法没。。

//耗时操作是在这里 ctx.service.task.pack
const local_path = await ctx.service.task.pack(clientid, platname);
      const updateItems = { local_path, status: 3 };
      await ctx.service.task.updateTasksStatus([{
        ...currentTaskObj,
        updateItems,
      }]);

@gxcsoccer

spawnSync 是同步的。。。 不要用任何带有 Sync 的 API。

https://www.npmjs.com/package/runscript

@atian25 嗯。。谢谢大佬指点,我的spawnSync是在被包裹在await函数中的,应该不会阻塞才对

跟包不包 await 没关系。。。 Sync 就一定是阻塞的。

@atian25 谢谢~

种棵树,给后人乘凉

const util = require('util');
const exec = util.promisify(require('child_process').exec);

async function lsExample() {
  const { stdout, stderr } = await exec('ls');
  console.log('stdout:', stdout);
  console.log('stderr:', stderr);
}
lsExample();

reference:https://nodejs.org/dist/latest-v10.x/docs/api/child_process.html

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kylezhang picture kylezhang  ·  3Comments

xcstream picture xcstream  ·  3Comments

bupafengyu picture bupafengyu  ·  3Comments

yuu2lee4 picture yuu2lee4  ·  3Comments

Webjiacheng picture Webjiacheng  ·  3Comments