在 express.js 应用程序和 RDS MySQL 5.6 上测试高流量负载时出现 ECONNRESET 和 ESOCKETTIMEDOUT 错误

问题描述

我有

在单个请求或“低”流量的情况下没有问题,但是 如果我尝试向系统强调发送更高负载的请求(我使用 artillery 进行 http 负载测试),我注意到基本上所有请求都挂起,直到它们因 ECONNRESETESOCKETTIMEDOUT 而失败错误

在以下测试中,我发送 30 个 GET 请求/秒,持续 10 秒:

config:
  target: 'http://localhost:8080'
  phases:
    - duration: 10
      arrivalRate: 30
scenarios:
  - flow:
      - log: "New virtual user running"
      - get:
          url: '/v1/myresource'
          headers:
            apikey: 'myapikey'

结果如下:

All virtual users finished
Summary report @ 17:06:35(+0100) 2021-03-21
  Scenarios launched:  300
  Scenarios completed: 0
  Requests completed:  0
  Mean response/sec: 2.31
  Response time (msec):
    min: NaN
    max: NaN
    median: NaN
    p95: NaN
    p99: NaN
  Scenario counts:
    0: 300 (100%)
  Errors:
    ESOCKETTIMEDOUT: 251
    ECONNRESET: 49

如您所见,所有请求都失败了。
另一方面,如果我将整个数据库导出到笔记本电脑上运行的本地 MysqL 并尝试相同的测试,则一切正常:

All virtual users finished
Summary report @ 17:08:14(+0100) 2021-03-21
  Scenarios launched:  300
  Scenarios completed: 300
  Requests completed:  300
  Mean response/sec: 18.79
  Response time (msec):
    min: 3518.9
    max: 9439
    median: 7795.5
    p95: 9237.9
    p99: 9281.9
  Scenario counts:
    0: 300 (100%)
  Codes:
    200: 300

我已经考虑过 RDS 实例的容量问题,但 db 指标似乎另有说明:

enter image description here

enter image description here

enter image description here

我也不认为是死锁问题,因为这些 GET 请求只涉及数据库上的简单 SELECT 语句(无写入)。

有人对我如何解决此问题有任何建议吗?

作为附加信息,我使用 knex.js 作为查询构建器库,使用 mysql2 作为驱动程序库。以下是连接配置:

const knex = require('knex')({
    debug: true,client: 'MysqL2',connection: {
        host: 'localhost',port: 3306,user: 'myuser',password: 'mypwd',database: 'mydb',charset: 'utf8mb4_bin'
    },pool: {
        min: 1,max: 5,}
});

解决方法

您可以通过启用增强监控和检查 CPU% 和 MEM% 指标来调试此问题。请查看以下文章了解如何操作。

https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html