webman中使用thinkorm动态连接数据库后不会自动释放导致数据库大量的sleep

JunH

业务场景

我这里类似于sass结构的 框架使用的webman 数据库使用的mysql8.0+thinkorm连接
业务需要:数据库是根据每家商户进行分库存储的,通过中间件进行数据库动态切换连接。

出现问题

现在动态连接各方面访问都没有问题,但是数据库连接量一直递增,目前已经跑到了1000多。一直担心奔溃的问题
我在中间件中使用动态连接,自动切换数据库连接代码如下

public function process(Request $request, callable $handler): Response
    {
        //请求控制器白名单,不能进行数据库模型操作,只用于回调接收数据
        $whiteController = Config::get('white_api_secret.white_controller');
        $controller = $request->controller;
        if (in_array($controller, $whiteController)) {
            $merchant_id = 0;
        } else {
            // 获取商户ID
            $merchant_id = $request->header('X-Merchant-ID');
        }

        // 检查商户ID是否有效
        if (!isset($merchant_id) || !is_numeric($merchant_id)) {
            return json(['code' => 400, 'msg' => 'Invalid merchant ID!']);
        }

        // 非法
        if ($merchant_id < 0) {
            return json(['code' => 400, 'msg' => 'Invalid merchant ID!']);
        }

        // 将当前商户的数据库配置存储在全局变量中
        global $merchant_dbs;

        // 等于0 属于硕昆平台端连接
        if ($merchant_id == 0) {
            $merchant_dbs[$merchant_id] = Config::get('thinkorm');
            // 初始化数据库连接
            Db::setConfig(Config::get('thinkorm'));
            Db::connect('mysql');
        }

        // 商户连接
        if ($merchant_id > 0) {
            $merchantInfoDb = $this->selectDbShopConfig($merchant_id);
            if (!is_array($merchantInfoDb)) {
                return $merchantInfoDb;
            }
            $merchant_dbs[$merchant_id] = $merchantInfoDb;
        }
        # 获取当前商户的数据库配置
        $db_config = Config::get('thinkorm');

        # 检查当前商户是否有对应的数据库配置
        if (!$db_config) {
            return json(['code' => 400, 'msg' => 'Database configuration not found for the merchant!']);
        }

        # 如果不存在直接退出
        if (!isset($merchant_dbs[$merchant_id])) {
            return json(['code' => 400, 'msg' => 'Database $merchant_id not save global!']);
        }

        if ($merchant_id > 0) {
            # 动态设置数据库
            Db::setConfig($merchant_dbs[$merchant_id]);
            # 动态连接数据库
            Db::connect('merchant' . $merchant_id);
        }

        return $handler($request);
    }

这是中间件中所执行的动态切换 也就是根据商户的id进行切换到指定的库。我发现这样使用连接量大量的sleep

1000 2 3
2个回答

walkor 打赏

判断下连接是否存在,存在就不再创建连接。
或者中间件里每次用完关闭连接

  • JunH 2024-05-17

    大佬 但是我判断连接后,数据库调用那里并不会主动切换到这个连上。而且中间件这个调用关闭连接 我不知道thinkorm怎么去调用

  • walkor 2024-05-17

    连接在调用 Db::connect(),连接在不调用。
    不知道怎么关闭就看他们文档呗。

  • JunH 2024-05-17

    大佬 意思是 我判断有连接 不调用Db::connect()。但是此次进入model连接的库他并不知道查询哪个 而且会查询到默认的初始化库上面去
    thinkorm文档上面没有这个玩意

  • walkor 2024-05-17

    所有model继承一个基类,中间件里根据条件更改基类的 $connection

  • JunH 2024-05-17

    明白了 感谢大佬

  • 酒米 2024-07-16

    我试了每次用完关闭连接,接口请求的时间增加了一点

Tinywan

你这是搞复杂化了吧!建议看看【SaaS多租户架构数据源动态切换解决方案】https://mp.weixin.qq.com/s/RszdlEXlyDIzv6Bn0xNl7g

  • JunH 2024-05-17

    大佬 其实和这个思路是一样的 我当时不想再模型中写入相关的数据库切换操作 在中间件直接去做的调用 但是每次进入接口都会重新连接 导致这种问题了 目前看看怎么改动量最小 感谢大佬

  • doit 2024-05-21

    @Tinywan 文章看了,切换是没有问题的,问题是预定义数据库配置是写死的,而不是动态添加的,还有一点是配置了多个,会导致项目启动时候就会有很多的链接存在,比如200个租户,即使是4个进程,就会有800个链接存在

  • Tinywan 2024-05-21

    连接存在会有什么问题?

  • JunH 2024-05-21

    @doit 大佬有什么不同的看法 他这么做其实最后是我一样的。我现在是一样的问题,切换还是会存在大量sleep,哪怕是调用完成close也还是无效

  • doit 2024-05-22

    mysql的连接数量是有限制的啊,多个租户多个进程,最终会导致mysql连接数占用完,还有就是消耗资源啊。。。

  • JunH 2024-05-22

    DB::connect 连接和它本身内置的切换数据库是 同理啊 你说的多个进程是指webman的启用的进程数吗

  • doit 2024-05-22

    是的

  • JunH 2024-05-22

    有解决方案吗

  • 酒米 2024-07-07

    你这个解决了吗?

  • JunH 2024-07-11

    没有解决,你有什么解决方案吗

  • 酒米 2024-07-11

    我也是刚接触😫

  • damao 2024-07-11

    复用一个数据库连接,操作数据库前用use 数据库语句切换数据库。切换时机可以在中间件里自动切换吧

×
🔝