在mysql knex中,将所有函数都创建为异步是一种糟糕的做法

在mysql knex中,将所有函数都创建为异步是一种糟糕的做法,mysql,node.js,async-await,es6-promise,knex.js,Mysql,Node.js,Async Await,Es6 Promise,Knex.js,我在node中使用了knex.js(带有从连接和主连接)来连接mysql 我的代码对150个用户运行良好,但当并发用户增加时,PM2中的堆使用率也达到100%或更高,服务器停止响应或响应非常慢 AWS CPU(5倍大的AWS ec2实例,8核CPU和32GB RAM)使用率为12-20% 应用程序以毫秒为单位响应JWT身份验证和pm2 有很多查询依赖于前面的查询结果,所以我将所有函数都创建为异步 问题点: 每小时都会为所有用户(约15万)打开一个编辑其内容的窗口(约3k实时并发) 我所做的临时解

我在node中使用了knex.js(带有从连接和主连接)来连接mysql

我的代码对150个用户运行良好,但当并发用户增加时,PM2中的堆使用率也达到100%或更高,服务器停止响应或响应非常慢

AWS CPU(5倍大的AWS ec2实例,8核CPU和32GB RAM)使用率为12-20%

应用程序以毫秒为单位响应JWT身份验证和pm2

有很多查询依赖于前面的查询结果,所以我将所有函数都创建为异步

问题点:

每小时都会为所有用户(约15万)打开一个编辑其内容的窗口(约3k实时并发)

我所做的临时解决方案:

实现群集解决了我的问题,但在群集终止时未关闭DB连接

我的怀疑:

当应用程序在集群中正常工作时,为什么应用程序在相同配置中不在集群中工作

async function authorize(req, res) {
  //decode aes-128 request
  let body = await helper.get_decoded_request(req);
  if (!body) {
    return res.status(200).json(await helper.error("Error occurs while decoding."));
  }
  const schema = joi.object({
    "client_id": joi.string().min(1).required(),
    "client_secret": joi.string().min(1).required()
  });
  try {
    await schema.validateAsync(body);
  }
  catch (err) {
    return res.status(200).json(await helper.error("Please send the valid request"));
  }

  try {
    //data base update and add function that writen in other file
    await user.update_user(data);
    await match.add_transaction(data);
  } catch (err) {
    return res.status(200).json(await helper.error("Please send the valid request"));
  }

  return res.status(200).json(await helper.success("Token added successfully.", jsontoken));
}
模型文件代码:

const { read_db, write_db } = require("./database");
async function add_transaction(data) {
  return await write_db.insert(data).table("users");
}
数据库文件:

var knex = require("knex");
const read_db = knex({
  client: "mysql",
  connection: {
    database: process.env.SLAVE_MYSQL_DB,
    host: process.env.SLAVE_MYSQL_HOST,
    port: process.env.SLAVE_MYSQL_PORT,
    user: process.env.SLAVE_MYSQL_USER,
    password: process.env.MYSQL_PASSWORD
  },
  pool: { min: 1, max: 10 }
});
const write_db = knex({
  client: "mysql",
  connection: {
    database: process.env.MYSQL_DB,
    host: process.env.MYSQL_HOST,
    port: process.env.MYSQL_PORT,
    user: process.env.MYSQL_USER,
    password: process.env.MYSQL_PASSWORD
  },
  pool: { min: 1, max: 10 }
});
module.exports = { read_db, write_db };

没有足够的信息来回答问题的根本原因,但是这些一般性的步骤可能会帮助解决问题

第一个也是最重要的部分是在本地复制减速,并在profiler中运行应用程序,以实际找出代码的哪些部分占用了所有CPU。使用
节点运行应用程序--inspect
允许您在Chrome browsers profiler中运行应用程序的运行配置文件

听起来你只是在运行一个单节点进程,所以很奇怪,你怎么能在8个内核中使用100%的CPU,而用户数却很低(少于1000?)。。。我想到的一件事是,如果你检查每个用户请求的密码散列,它实际上可能会很快开始使用大量CPU

如果这确实是问题所在,您可以对应用程序实施JSON Web令牌支持,其中密码仅用于获取访问令牌,与密码身份验证相比,访问令牌的验证速度非常快

当您的基本应用程序工作正常时,您应该开始考虑如何在单个实例上运行多个服务器进程,以便能够更好地利用所有CPU核心

编辑:

听起来5核实例的12-20%大约是单核实例的100%。因此,你的应用程序似乎正在使CPU饱和

关于堆使用情况,如果您分析应用程序,您可以看到是否是垃圾收集开始停止应用程序

一个原因可能是您实际上创建了太多的垃圾,这在某个时候开始影响性能。例如,如果将默认堆大小从1.7GB增加到8GB
节点--max old space size=8092
有帮助,您也可以尝试一下


除了垃圾收集之外,例如,如果要从DB返回数万行,仅将它们解析为javascript对象可能会使CPU饱和。所以,分析仍然是找出问题所在的正确方法。默认情况下,在knex中解析日期非常慢(当它们转换为
Date
对象时)。

是否为每次更新创建新连接?例如,是否在
user.update\u user
方法中创建了新的conn?如果可能的话,展示一下你在用这种方法做什么。我使用的是池。我已经添加了代码供您参考。我更正了我的问题。AWS CPU使用率为12-20%,pm2上显示的堆使用率为101%,然后应用程序暂时停止响应,直到应用程序重新启动。应用程序已经集成了JWT身份验证和pm2。每小时都会有一个槽供所有用户(约1.5 lac)编辑他们的内容(约3k实时并发)。@waseemasgar更新了回复,添加了一些推测感谢您的帮助。还有一个问题,我是否也应该增加线程池大小?默认情况下它是4。@waseemasgar可能不会有任何区别,因为这些CPU利用率表明您正在使这4个线程中的单个线程饱和。。。