webman框架内存很大程度出现泄漏,如何能快速进行排查。

JunH

webman框架使用服务器内存不正常

我的业务服务器有5台
但是现在服务器的内存达到了58%左右 cpu在20以下
有什么办法能排查吗?
以下是两台服务器的概况
现在只能在每天的时候进行restart 重启来降低内存
工作进程数一台服务器开启24个
截图

截图

950 3 8
3个回答

nitron

随着连接数增多,占用内存不断增大是正常的。当连接释放时php也不会立刻将所有内存归还给操作系统也是正常的,因为这部分内存可留着下次使用,也就是如果连接数从0再次增多会复用这部分内存,只要不是无限制的增长就问题不大

至于是否内存泄漏,内存泄漏发生在使用了无限膨胀的静态数组的情况,这个要自行排查了

https://www.workerman.net/doc/webman/others/memory-leak.html

  • JunH 2024-09-24

    但是我的业务群体都是在晚上10点到凌晨4点才高峰使用系统,按理白天会降下来才对。导致我现在只能通过restart来进行释放内存

  • nitron 2024-09-24

    未达释放阈值,内存留着不释放也正常,我记得有配置请求达到一点数量自动重启进程的设置

  • JunH 2024-09-24

    memory_limit的php.ini配置的这个,我看文档描述的是达到这个设置值monitor会进行自动释放

  • tanhongbin 2024-09-25

    直接在代码中 config/process.php monitor 的 options 下面 'memory_limit' => 30M也是可以的,不需要php.ini 而且内存只要不是一直增长 就没问题 假如一台机器 一共开了 50个进程 每个进程处理的业务量很大 每个进程占用几十M 很正常 你算一下 这就多少了 也不能 让马儿跑 又不给吃草

  • tanhongbin 2024-09-25

    兄弟 你每个进程这么大内存 啥业务呀 多大的请求呀 ,我压测1万并发 都到不了你这个内存使用量 头一次看见每个进程使用这么多内存的,你是不是 使用啥composer包 有内存泄漏的隐患?

  • JunH 2024-09-25

    业务请求量也不算是很大,就大概高峰期200W的请求量。并发qps也才60-80/s。真的奇怪的很
    "require": {
    "php": ">=7.4",
    "workerman/webman-framework": "^1.5.0",
    "monolog/monolog": "^2.0",
    "psr/container": "1.1.1",
    "webman/think-orm": "^1.1",
    "illuminate/redis": "^8.83",
    "illuminate/events": "^8.83",
    "firebase/php-jwt": "^6.4",
    "topthink/think-validate": "^2.0",
    "webman/captcha": "^1.0",
    "overtrue/pinyin": "^4.0",
    "workerman/crontab": "^1.0",
    "webman/push": "^1.0",
    "qiniu/php-sdk": "^7.9",
    "phpoffice/phpspreadsheet": "^1.28",
    "react/http": "^1.9",
    "ext-json": "",
    "ext-curl": "
    ",
    "overtrue/wechat": "~5.0",
    "chillerlan/php-qrcode": "^4.3",
    "predis/predis": "^2.2",
    "yzh52521/easyhttp": "^1.1"
    }也就是这些东西啊

  • nitron 2024-09-25

    自己检查代码吧

  • tanhongbin 2024-09-25

    这个得你自己排查一下了 如果是导出或者读取 excel文件 导致的 建议用 https://xlswriter-docs.viest.me/ 这个扩展做

  • JunH 2024-09-25

    好的 我先观察下吧

walkor 打赏

app/middleware/MemoryDetect.php

<?php
namespace app\middleware;

use Webman\App;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;

class MemoryDetect implements MiddlewareInterface
{
    public function process(Request $request, callable $handler) : Response
    {
        $response = $handler($request);
        $worker = App::worker();
        if (!$worker || $worker->id !== 0) {
            return $response;
        }
        static $memory = 0;
        $uri = $request->uri();
        $method = $request->method();
        if ($memory === 0) {
            $memory = memory_get_usage(true);
        }
        $usage = memory_get_usage(true);
        $diff = $usage - $memory;
        $memory = $usage;
        if ($diff) {
            file_put_contents(runtime_path('logs/memory-' . date('Y-m-d') . '.log'), date('Y-m-d H:i:s') . " $memory $diff $method $uri \n", FILE_APPEND);
        }
        return $response;
    }

}

config/middleware.php

return [
    '' => [
        \app\middleware\MemoryDetect::class,
    ]
];

执行reload,这样会记录每个请求当前占用内存和增加的内存,方便排查哪个请求可能有内存泄露,然后进一步排查代码。

最开始启动阶段会记录一些日志是正常的不用关心,因为随着请求进来webman会加载php文件到内存,内存会有增加。
随着所有文件载入后内存会趋向稳定,过一段时间如果陆续还有一些的日志记录并且总内存在无限增长说明对应的请求可能有内存泄露。

  • JunH 2024-09-26

    好的,感谢大佬。但是这个$memory = memory_get_usage(true)第一次获取不用写在$response = $handler($request)这个前面吗,没有向下透传时不应该先记录内存量,直到完成时在次获取后相减吗。有点没理解到

  • walkor 2024-09-26

    $memory初始值在哪里设置不重要,我们不关注前面的日志,我们关注后续的日志。

  • JunH 2024-09-26

    明白了。大概需要等待多久才能确定是否这类方法存在泄露呢

  • walkor 2024-09-26

    看情况,如果接口少的话按照你的请求量等估计10分钟差不多了

JonWong

大佬,目前这个问题解决了吗?蹲个解决办法

  • 暂无评论
×
🔝