我的業(yè)務(wù)服務(wù)器有5臺(tái)
但是現(xiàn)在服務(wù)器的內(nèi)存達(dá)到了58%左右 cpu在20以下
有什么辦法能排查嗎?
以下是兩臺(tái)服務(wù)器的概況
現(xiàn)在只能在每天的時(shí)候進(jìn)行restart 重啟來降低內(nèi)存
工作進(jìn)程數(shù)一臺(tái)服務(wù)器開啟24個(gè)
隨著連接數(shù)增多,占用內(nèi)存不斷增大是正常的。當(dāng)連接釋放時(shí)php也不會(huì)立刻將所有內(nèi)存歸還給操作系統(tǒng)也是正常的,因?yàn)檫@部分內(nèi)存可留著下次使用,也就是如果連接數(shù)從0再次增多會(huì)復(fù)用這部分內(nèi)存,只要不是無限制的增長就問題不大
至于是否內(nèi)存泄漏,內(nèi)存泄漏發(fā)生在使用了無限膨脹的靜態(tài)數(shù)組的情況,這個(gè)要自行排查了
但是我的業(yè)務(wù)群體都是在晚上10點(diǎn)到凌晨4點(diǎn)才高峰使用系統(tǒng),按理白天會(huì)降下來才對(duì)。導(dǎo)致我現(xiàn)在只能通過restart來進(jìn)行釋放內(nèi)存
未達(dá)釋放閾值,內(nèi)存留著不釋放也正常,我記得有配置請(qǐng)求達(dá)到一點(diǎn)數(shù)量自動(dòng)重啟進(jìn)程的設(shè)置
memory_limit的php.ini配置的這個(gè),我看文檔描述的是達(dá)到這個(gè)設(shè)置值monitor會(huì)進(jìn)行自動(dòng)釋放
直接在代碼中 config/process.php monitor 的 options 下面 'memory_limit' => 30M也是可以的,不需要php.ini 而且內(nèi)存只要不是一直增長 就沒問題 假如一臺(tái)機(jī)器 一共開了 50個(gè)進(jìn)程 每個(gè)進(jìn)程處理的業(yè)務(wù)量很大 每個(gè)進(jìn)程占用幾十M 很正常 你算一下 這就多少了 也不能 讓馬兒跑 又不給吃草
兄弟 你每個(gè)進(jìn)程這么大內(nèi)存 啥業(yè)務(wù)呀 多大的請(qǐng)求呀 ,我壓測(cè)1萬并發(fā) 都到不了你這個(gè)內(nèi)存使用量 頭一次看見每個(gè)進(jìn)程使用這么多內(nèi)存的,你是不是 使用啥composer包 有內(nèi)存泄漏的隱患?
業(yè)務(wù)請(qǐng)求量也不算是很大,就大概高峰期200W的請(qǐng)求量。并發(fā)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"
}也就是這些東西啊
這個(gè)得你自己排查一下了 如果是導(dǎo)出或者讀取 excel文件 導(dǎo)致的 建議用 https://xlswriter-docs.viest.me/ 這個(gè)擴(kuò)展做
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,
]
];
執(zhí)行reload,這樣會(huì)記錄每個(gè)請(qǐng)求當(dāng)前占用內(nèi)存和增加的內(nèi)存,方便排查哪個(gè)請(qǐng)求可能有內(nèi)存泄露,然后進(jìn)一步排查代碼。
最開始啟動(dòng)階段會(huì)記錄一些日志是正常的不用關(guān)心,因?yàn)殡S著請(qǐng)求進(jìn)來webman會(huì)加載php文件到內(nèi)存,內(nèi)存會(huì)有增加。
隨著所有文件載入后內(nèi)存會(huì)趨向穩(wěn)定,過一段時(shí)間如果陸續(xù)還有一些的日志記錄并且總內(nèi)存在無限增長說明對(duì)應(yīng)的請(qǐng)求可能有內(nèi)存泄露。
好的,感謝大佬。但是這個(gè)$memory = memory_get_usage(true)第一次獲取不用寫在$response = $handler($request)這個(gè)前面嗎,沒有向下透?jìng)鲿r(shí)不應(yīng)該先記錄內(nèi)存量,直到完成時(shí)在次獲取后相減嗎。有點(diǎn)沒理解到