背景
这个古怪的需求来自于懒~, 懒得重新写一套属于 swoole 的方法了
当然在进程中直接复用 Db 类方法,验证类方法也是很容易的。
示例
这里以日志方法 log 为例:
<?php
ini_set("display_errors", "On");
ini_set("error_reporting", "E_ALL");
use Swoole\Process;
use Swoole\Coroutine;
$pool = new Process\Pool(2);
// $pool->set(['enable_coroutine' => true]);
// 加载 autoload
require __DIR__ . '/../vendor/autoload.php';
$pool->on('WorkerStart', function (Process\Pool $pool, $workerId) {
/** 当前是 Worker 进程 */
static $running = true;
Process::signal(SIGTERM, function () use (&$running) {
$running = false;
echo "TERM\n";
});
echo("[Worker #{$workerId}] WorkerStart, pid: " . posix_getpid() . "\n");
while ($running) {
// Coroutine::sleep(1);
// echo "sleep 5\n";
// sleep(5);
// require __DIR__ . '/../vendor/autoload.php';
var_dump('====');
try {
// 这里来启用ThinkPhp并调用
$app = new \think\App();
$app->debug(true);
$app->http->run(); // 使用run方法来启动框架,参见tp6的index.php入口文件
$app->log->write("test log...");
} catch (\Exception $e){
echo $e->getMessage() . PHP_EOL;
echo $e->getTraceAsString() . PHP_EOL;
}
echo "sleep 5\n";
sleep(5);
}
});
$pool->on('WorkerStop', function (\Swoole\Process\Pool $pool, $workerId) {
echo("[Worker #{$workerId}] WorkerStop\n");
});
$pool->start();
当然,改完后的内存占用还是有牺牲的。
2022-12-06 15:25:04 #usedMemory:1.277M==========>>
2022-12-06 15:25:06 #usedMemory:1.277M==========>>
2022-12-06 15:25:07 #usedMemory:1.277M==========>>
2022-12-06 15:25:07 #usedMemory:1.277M==========>>
2022-12-06 15:25:09 #usedMemory:1.277M==========>>
2022-12-06 15:25:11 #usedMemory:1.277M==========>>
2022-12-06 15:25:12 #usedMemory:1.277M==========>>
2022-12-06 15:25:13 #usedMemory:1.277M==========>>
2022-12-06 15:25:14 #usedMemory:1.277M==========>>
2022-12-06 15:25:15 #usedMemory:1.277M==========>>
---- before vs after ----
2022-12-06 15:48:42 #usedMemory:4.843M==========>>
2022-12-06 15:48:43 #usedMemory:1.554M==========>>
2022-12-06 15:48:54 #usedMemory:1.593M==========>>
2022-12-06 15:48:57 #usedMemory:4.843M==========>>
2022-12-06 15:49:00 #usedMemory:1.593M==========>>
2022-12-06 15:49:06 #usedMemory:1.554M==========>>
2022-12-06 15:49:07 #usedMemory:1.554M==========>>
2022-12-06 15:49:09 #usedMemory:1.593M==========>>
2022-12-06 15:49:13 #usedMemory:4.883M==========>>
2022-12-06 15:49:14 #usedMemory:1.554M==========>>
参考:
让Swoole完美支持ThinkPHP5_jeremyke07的博客-CSDN博客_thinkphp5 使用swoole
让swoole完美支持ThinkPHP6.0_丁丁丁梦涛的博客-CSDN博客
后续
今天看日志,发现 swoole 加载 thinkphp6 后存在内存泄漏问题,一开始 1.xM,到后来13.xM。
应该是程序有问题,看了下可能导致 swoole 内存泄漏的问题,详见:编程须知 | Swoole4 文档
初步判断这个问题应该是 thinkphp6 在初始化时有一些静态变量(或全局变量)导致,我们修改代码为闭包形式载入,避免每次初始化时静态变量累积导致的内存泄漏问题。
ini_set("display_errors", "On");
ini_set("error_reporting", "E_ALL");
use Swoole\Process;
use Swoole\Coroutine;
$pool = new Process\Pool(2);
// $pool->set(['enable_coroutine' => true]);
require __DIR__ . './../vendor/autoload.php';
$thinkApp = new \think\App(); // 在外部初始化,以闭包形式传入多进程
$pool->on('WorkerStart', function (Process\Pool $pool, $workerId)
use ($thinkApp)
{
/** 当前是 Worker 进程 */
static $running = true;
Process::signal(SIGTERM, function () use (&$running) {
$running = false;
echo "TERM\n";
});
echo("[Worker #{$workerId}] WorkerStart, pid: " . posix_getpid() . "\n");
while ($running) {
// Coroutine::sleep(1);
// echo "sleep 5\n";
// sleep(5);
// require __DIR__ . '/../vendor/autoload.php';
var_dump('====');
try {
// $thinkApp = new \think\App();
// $thinkApp->debug(true);
$thinkApp->http->run();
// $thinkApp->log->write("test onWorkerStart");
} catch (\Exception $e){
echo $e->getMessage() . PHP_EOL;
echo $e->getTraceAsString() . PHP_EOL;
}
echo "sleep 1\n";
sleep(1);
$usedMemory = memory_get_usage();
$usedMemory = round($usedMemory / 1024 / 1024, 3);
echo date('Y-m-d H:i:s') . " #usedMemory:{$usedMemory} M==========>>\n";
}
});
$pool->on('WorkerStop', function (\Swoole\Process\Pool $pool, $workerId) {
echo("[Worker #{$workerId}] WorkerStop\n");
});
$pool->start();
ok,修改完后观察一段时间,一直稳定在 1.5M左右~