使用 NestJS 队列时关闭 redis 连接

Posted

技术标签:

【中文标题】使用 NestJS 队列时关闭 redis 连接【英文标题】:Close redis connection when using NestJS Queues 【发布时间】:2020-11-08 12:12:05 【问题描述】:

我正在尝试在 NestJS 项目中设置 E2E 测试,但是,jest 输出如下所示:

Jest did not exit one second after the test run has completed

经过大量阅读,这是因为有一些资源尚未释放,经过一些调试后,它打开了由ioredis 创建的redis 的开放连接,bull 使用该连接,NestJS 使用它来执行任务队列处理。问题是我在测试代码中没有对连接的引用,那么我该如何关闭它呢?我正在像这样在afterAll jest 的钩子中拆除 Nest 应用程序:

  afterAll(async () => 
    await app.close();
  );

但它什么也没做,连接仍然存在,并且开玩笑的错误消息仍然存在。我知道我可以将--forceExit 添加到jest 命令中,但这并不能解决任何问题,只是将问题隐藏在地毯下。

【问题讨论】:

解决了这个问题吗?我遇到了同样的问题,在使用--detectOpenhandles 后我意识到ioredis StandaloneConnector 有一个tcp 连接打开 【参考方案1】:

这花了我一段时间才弄清楚。您需要在 afterAll 挂钩中关闭模块。我可以通过查看 nestJS Bull 存储库中的测试找到这一点。

describe('RedisTest', () => 
  let module: TestingModule;
  beforeAll(async () => 

    module = Test.createTestingModule(
      imports: [
        BullModule.registerQueueAsync(
          name: 'test2',
        ),
      ],

    );
  );

  afterAll(async () => 
    await module.close();
  );
);

https://github.com/nestjs/bull/blob/master/e2e/module.e2e-spec.ts

【讨论】:

【参考方案2】:

在几乎陷入抑郁的挣扎之后,我找到了一个对我有用的解决方案。 我正在使用"@nestjs/bull": "^0.3.1""bull": "^3.21.1"。 由于来自bul 包的队列使用redis,因此尽管模块和应用程序已关闭,但它仍保持连接打开。

    await moduleRef.close();
    await app.close();

我意识到,当使用--detectOpenHandles 同时依赖leaked-handles 库获取更多信息时,您会在控制台中看到类似这样的内容:

    tcp stream 
       fd: 20,
       readable: true,
       writable: false,
       address: ,
       serverAddr: null
    

    tcp handle leaked at one of: 
    at /media/user/somePartitionName/Workspace/Nest/project- 
    name/node_modules/ioredis/built/connectors/StandaloneConnector.js:58:45
    tcp stream 
       fd: 22,
       readable: true,
       writable: true,
       address:  address: '127.0.0.1', family: 'IPv4', port: 34876 ,
       serverAddr: null
    

解决方案 使用beforEach() & afterEach()

beforEach() 中,添加此指令以获取队列实例:
    queue = moduleRef.get(getQueueToken("queuename"));
afterEach() 中,像这样关闭队列:(同时关闭您的应用和模块以便更好地练习)
    await queue.close();

注意

使用 beforAll()afterAll() 不起作用,并且发生同样的问题,至少从我尝试过的情况来看,beforEach()afterEach() 结合使用。

【讨论】:

现在的问题是,您正在为每个测试分配和关闭连接,似乎您泄漏了连接或代码效率低下(泄漏周期),谢天谢地,我没有接触 nodejs再次(我知道不是nodejs的错,但仍然如此)。

以上是关于使用 NestJS 队列时关闭 redis 连接的主要内容,如果未能解决你的问题,请参考以下文章

如何将@liaoliaots/nestjs-redis redis 连接传递给全局保护构造函数

使用 TypeORM 和 NestJs 和 Typescript 创建新迁移时出错 [关闭]

Redis(五)-特性-消息队列

基于异步消息队列List lpush-brpop(rpush-blpop)

使用 Nestjs 监听多个 RabbitMQ 队列

php+redis实现消息队列