luoxiaojun1992 / laravel-tars

Tars driver for laravel.
Apache License 2.0
28 stars 9 forks source link

你好,请问有遇到过数据库句柄一直不释放问题吗? #19

Closed dmf-code closed 3 years ago

dmf-code commented 3 years ago

最近发现数据库请求会出现句柄一直不释放,导致会造成 mysql Too many connections。这个是不是框架没有请求结束将句柄回收的问题? php-fpm 模型每次请求都会释放进程,所以 mysql 连接也会同时释放,然后现在常驻之后就会出现一直不释放的问题。

luoxiaojun1992 commented 3 years ago

数据库句柄是由php的GC来回收的,不是框架回收的,pdo的连接是存在laravel app容器里,app容器是每次请求时重新生成的,并不是常驻在内存中,可以先检查一下内存使用的情况,判断GC是否起作用 @dmf-code

dmf-code commented 3 years ago

数据库句柄是由php的GC来回收的,不是框架回收的,pdo的连接是存在laravel app容器里,app容器是每次请求时重新生成的,并不是常驻在内存中,可以先检查一下内存使用的情况,判断GC是否起作用 @dmf-code

好的

luoxiaojun1992 commented 3 years ago

另外确认下你的请求量(QPS)是不是和php-fpm测试的一样,把数据库的连接存活时间设置长一点,再测试验证一下php是否自动断开连接,谢谢

dmf-code commented 3 years ago

另外确认下你的请求量(QPS)是不是和php-fpm测试的一样,把数据库的连接存活时间设置长一点,再测试验证一下php是否自动断开连接,谢谢

好的

dmf-code commented 3 years ago

BaiduShurufa_2020-10-26_14-12-44

这里使用 include 会不会造成多次加载,导致内存泄漏问题。因为我使用

Route::get('test', function () {
    return [
        'memory_get_usage' => memory_get_usage(),
    ];
});

发现返回的内存也是在不断递增的。

image

容器在实例化的时候,好像是会存在自身调用的情况,会不会是这样导致 phpGC 失效了。

luoxiaojun1992 commented 3 years ago

你的vendor包是老的,更新一下后再测试一下

dmf-code commented 3 years ago

你的vendor包是老的,更新一下后再测试一下

好的

dmf-code commented 3 years ago

我使用 composer require "luoxiaojun1992/laravel-tars:*"composer update 都更新不到最新的代码呢?这个有同步到 composer 镜像库吗?

luoxiaojun1992 commented 3 years ago

我使用 composer require "luoxiaojun1992/laravel-tars:*"composer update 都更新不到最新的代码呢?这个有同步到 composer 镜像库吗?

试一下 composer update "luoxiaojun1992/laravel-tars:dev-master"

dmf-code commented 3 years ago

我使用 composer require "luoxiaojun1992/laravel-tars:*"composer update 都更新不到最新的代码呢?这个有同步到 composer 镜像库吗?

试一下 composer update "luoxiaojun1992/laravel-tars:dev-master"

image 还是不行呢

luoxiaojun1992 commented 3 years ago

你原先安装的是什么版本的?试一下下面的命令

composer remove 'luoxiaojun1992/laravel-tars'
composer clearcache
composer install 'luoxiaojun1992/laravel-tars:dev-master'
dmf-code commented 3 years ago

你原先安装的是什么版本的?试一下下面的命令

composer remove 'luoxiaojun1992/laravel-tars'
composer clearcache
composer install 'luoxiaojun1992/laravel-tars:dev-master'

可以安装最新的包了

dmf-code commented 3 years ago

内存还是存在泄漏呢 image

image image 数据库这些还是没有释放呢

dmf-code commented 3 years ago

App 文件这里多次加载文件应该会造成内存不断变大 image

然后数据库句柄没有释放,会不会和 App 文件多次加载有关。

luoxiaojun1992 commented 3 years ago

调用createApp的那部分代码发出来我看下

dmf-code commented 3 years ago

src/App.php

    /**
     * @param \Symfony\Component\HttpFoundation\Request $request
     * @return mixed
     */
    public static function getApp($request)
    {
        static::setTarsDeployCfg(config('tars.deploy_cfg'));

        $oldApp = app();

        $application = static::createApp();

        $oldApp->forgetInstance('app');

        /** @var Kernel $kernel */
        $kernel = $application->make(Kernel::class);

        $request->enableHttpMethodParameterOverride();
        $application->instance('request', $request);
        Facade::clearResolvedInstance('request');
        $kernel->bootstrap();

        config(['tars.deploy_cfg' => static::getTarsDeployCfg()]);
        Boot::handle(true);

        return $application;
    }

src/Route/TarsRoute.php

    protected function handle($illuminateRequest)
    {
        if (ob_get_level() > 0) {
            ob_end_clean();
        }
        ob_start();
        $isObEnd = false;

        event('laravel.tars.requesting', [$illuminateRequest]);
        var_dump(getmypid());
        var_dump(memory_get_usage());
        //Laravel App 创建完必须
        $application = $this->app($illuminateRequest);
        var_dump(memory_get_usage());
        if (Util::isLumen()) {
            $illuminateResponse = $application->dispatch($illuminateRequest);
        } else {
            /** @var Kernel $kernel */
            $kernel = $application->make(Kernel::class);
            $illuminateResponse = $kernel->handle($illuminateRequest);
        }

        if (!($illuminateResponse instanceof BinaryFileResponse)) {
            $content = $illuminateResponse->getContent();
            if (strlen($content) === 0 && ob_get_length() > 0) {
                $illuminateResponse->setContent(ob_get_contents());
                ob_end_clean();
                $isObEnd = true;
            }
        }

        if (!$isObEnd) {
            ob_end_flush();
        }

        return [$illuminateRequest, $illuminateResponse];
    }
luoxiaojun1992 commented 3 years ago

include进来的变量是局部变量,并不是全局的

dmf-code commented 3 years ago

include进来的变量是局部变量,并不是全局的

我的理解是加载到了 worker 进程去了,每一次请求内存都会增大,而且没有释放。

luoxiaojun1992 commented 3 years ago

src/vendor/luoxiaojun1992/laravel-tars/src/App.php: 34行

改成 $oldApp->flush();,再试下,谢谢。

dmf-code commented 3 years ago

好的,我明天再试试,下班了没有工作环境。

---原始邮件--- 发件人: "罗晓俊"<notifications@github.com> 发送时间: 2020年10月26日(周一) 晚上8:47 收件人: "luoxiaojun1992/laravel-tars"<laravel-tars@noreply.github.com>; 抄送: "dmf-code"<1015814408@qq.com>;"Mention"<mention@noreply.github.com>; 主题: Re: [luoxiaojun1992/laravel-tars] 你好,请问有遇到过数据库句柄一直不释放问题吗? (#19)

src/vendor/luoxiaojun1992/laravel-tars/src/App.php: 34行

改成 $oldApp->flush();,再试下,谢谢。

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

luoxiaojun1992 commented 3 years ago

好的,多谢

dmf-code commented 3 years ago

image 内存增长变小了,不过还是会增长

luoxiaojun1992 commented 3 years ago

数据库连接有释放吗

dmf-code commented 3 years ago

数据库连接有释放吗

没有

luoxiaojun1992 commented 3 years ago

你测试的请求了几次,再多请求一段时间。没有用到协程吧

dmf-code commented 3 years ago

你测试的请求了几次,再多请求一段时间。没有用到协程吧

请求10多次了,没有用到协程

luoxiaojun1992 commented 3 years ago

用的swoole什么版本?

dmf-code commented 3 years ago

image

luoxiaojun1992 commented 3 years ago

https://wiki.swoole.com/wiki/page/696.html

luoxiaojun1992 commented 3 years ago

编译的时候不要使用 --enable-coroutine

dmf-code commented 3 years ago

不好意思,刚才看错了环境了。刚才的是测试环境,我开发环境是这个配置 image

dmf-code commented 3 years ago

编译的时候不要使用 --enable-coroutine

4.0 版本开启协程会有影响吗?代码是没有使用协程功能的

luoxiaojun1992 commented 3 years ago

swoole默认会在request回调创建协程,框架不支持任何形式的协程,包括自动创建的

dmf-code commented 3 years ago

swoole默认会在request回调创建协程,框架不支持任何形式的协程,包括自动创建的

好的,那我是使用 docker 构建的 node ,重新编译 swoole 是不是就要重新编写 dockerfile 进行定制才行?官方 tars-node有没有添加环境变量然后在在编译的时候不开启协程?

luoxiaojun1992 commented 3 years ago

不太清楚,docker镜像不是我做的,这个只能你们自己解决了,4.0好像支持通过配置动态关闭,应该可以通过tars后台创建的服务配置模版添加,这个和tars没有关系,是laravel的限制

luoxiaojun1992 commented 3 years ago

可以看下能不能在容器里临时重新编译下swoole测试下内存泄漏的问题

dmf-code commented 3 years ago

不太清楚,docker镜像不是我做的,这个只能你们自己解决了,4.0好像支持通过配置动态关闭,应该可以通过tars后台创建的服务配置模版添加,这个和tars没有关系,是laravel的限制

好的,谢谢

dmf-code commented 3 years ago

可以看下能不能在容器里临时重新编译下swoole测试下内存泄漏的问题

好的,我问一下运维能不能重新编译一下 swoole

dmf-code commented 3 years ago

image

image

我的版本是不用配置 --enable-coroutine 的,只需要动态配置关闭就行了。

我关闭协程之后也是存在之前的问题。

dmf-code commented 3 years ago

4.0.0或更高版本仅支持PHP7 4.0.1版本开始去除了--enable-coroutine编译选项,改为动态配置

enable_coroutine 根据 RFC1011 实现

enable_coroutine 选项相当于在回调中关闭以前版本的SW_COROUTINE宏开关, 关闭时在回调事件中不再创建协程,但是保留用户创建协程的能力。

配置方法 在php.ini配置 swoole.enable_coroutine = 'Off' (推荐, 可见 ini配置文档 ) $server->set(['enable_coroutine' => false]); swoole_async_set(['enable_coroutine' => false]);

图片的内容

luoxiaojun1992 commented 3 years ago

你是怎么关闭的?

dmf-code commented 3 years ago

你是怎么关闭的?

php.ini$server->set 两个方法都使用了

luoxiaojun1992 commented 3 years ago

php.ini改完之后重启服务了吗

luoxiaojun1992 commented 3 years ago

server->set 是server启动的时候加的吗 还有之前改的$oldApp->flush还在吗

dmf-code commented 3 years ago

php.ini改完之后重启服务了吗

重启了,然后 php --ri swoole 显示协程也是Off

dmf-code commented 3 years ago

server->set 是server启动的时候加的吗 还有之前改的$oldApp->flush还在吗

是的,在 tars-server 创建 http 服务的时候添加 setting。之前的代码也还在

luoxiaojun1992 commented 3 years ago

server->set 是server启动的时候加的吗 还有之前改的$oldApp->flush还在吗

是的,在 tars-server 创建 http 服务的时候添加 setting。之前的代码也还在

多请求几次,观察一段时间,不要只请求一会儿,GC不是立即回收的

$kernel->bootstrap();下面加var_dump(spl_object_id(DB::getFacadeApplication()));,看下打印什么东西

dmf-code commented 3 years ago

server->set 是server启动的时候加的吗 还有之前改的$oldApp->flush还在吗

是的,在 tars-server 创建 http 服务的时候添加 setting。之前的代码也还在

多请求几次,观察一段时间,不要只请求一会儿,GC不是立即回收的

$kernel->bootstrap();下面加var_dump(spl_object_id(DB::getFacadeApplication()));,看下打印什么东西

好的

dmf-code commented 3 years ago

phpGC 应该是生效了,内存确实是回收了,然后数据库句柄也随着资源回收而释放掉。打印的是不同的两个 idimage

luoxiaojun1992 commented 3 years ago

好的,再观察下。建议修改代码后都进行下回归,看会不会内存泄露,laravel框架内部逻辑复杂,不能完全排除。