【问题标题】:Slack webhooks cause cls-hooked request context to orphan mysql connectionsSlack webhooks 导致 cls-hooked 请求上下文孤立 mysql 连接
【发布时间】:2020-07-27 15:27:37
【问题描述】:

主要问题: 我们有一个可爱的小快递应用程序,几个月来一直在粉碎它,没有任何问题。我们通过按需打开连接来管理我们的数据库连接,然后使用cls-hooked 库“按请求”缓存它。在请求结束时,我们释放连接,这样我们的连接池就不会用完。经典的。在几个月和许多连接的过程中,我们从未“泄露”连接。到目前为止!输入...松弛!我们使用 slack 事件处理程序如下:

app.use('/webhooks/slack', slackEventHandler.expressMiddleware());

我们有点像任何其他请求一样认为它,但是松弛请求似乎与我们的 cls-hooked 用法很奇怪。例如,我们使用 node-ts 和 nodemon 在本地运行我们的应用程序(例如,您更改代码,应用程序会自动重启)。每次应用程序在我们的开发机器上本地重新启动,并且您尝试使用 slack 事件时,突然当我们释放连接的中间件尝试这样做时,它认为会话中没有任何内容。然后,当您使用普通端点时...它可以正常工作,并且基本上似乎 reset 松弛以再次正常工作。我们现在害怕去刺激我们的松弛集成,因为我们担心我们的松弛“请求”会饿死我们的连接池。

背景

我们的 package.json 的相关子集:

{
  "@slack/events-api": "^2.3.2",
  "@slack/web-api": "^5.8.0",
  "express": "~4.16.1",
  "cls-hooked": "^4.2.2",
  "mysql2": "^2.0.0",
}

构成 cls-hooked 会话的中间件

import { session } from '../db';

const context = (req, res, next) => {
  session.run(() => {
    session.bindEmitter(req);
    session.bindEmitter(res);
    next();
  });
};

export default context;

释放我们连接的中间件

export const dbReleaseMiddleware = async (req, res, next) => {
  res.on('finish', async () => {
    const conn = session.get('conn');
    if (conn) {
      incrementConnsReleased();
      await conn.release();
    }
  });
  next();
};

按需创建连接并将其存储在“会话”中的代码

  const poolConn = await pool.getConnection();
  if (session.active) {
    session.set('conn', poolConn);
  }
  return poolConn;

首先设置会话的代码

export const session = clsHooked.createNamespace('our_company_name');

如果你走到这一步,恭喜。任何帮助表示赞赏!

旁注:你不能付钱给我写一个更令人困惑的标题......

【问题讨论】:

    标签: mysql node.js express slack-api cls-hooked


    【解决方案1】:

    想通了!似乎我们在节点版本的 slack 的 API 中发现了以下行为(似乎只发生在 mac 计算机上......有时

    问题在于这是在 express 应用程序的上下文中,因此 Slack 正在管理其自己的事件处理程序系统 + 事物的 http 端与 express 之间的接口(例如返回 200 或 500 或其他)。所以似乎发生的事情是......

    // you have some slack event handler
    slackEventHandler.on('message', async (rawEvent: any) => {
      const i = 0;
      i = i + 1;
      // at this point, the http request has not returned 200, it is "pending" from express's POV
      await myService.someMethod();
      // ^^ while this was doing its async thing, the express request returned 200.
      // so things like res.on('finished') all fired and all your middleware happened
      // but your event handler code is still going
    });
    

    所以我们最终创建了一个手动调用来释放松弛事件处理程序中的连接。诡异的!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-26
      • 2019-03-05
      • 2013-12-20
      • 1970-01-01
      相关资源
      最近更新 更多