使用 AdapterMan 扩展加速您的 Laravel 项目

项目地址 https://github.com/joanhey/AdapterMan

测试有问题,主要集中于 session 上,暂不可用,此处仅记录下代码修改点

在项目根目录下新增 server.php 和 start.php

1、server.php

 <?php

require_once __DIR__ . '/vendor/autoload.php';

use Adapterman\Adapterman;
use Workerman\Worker;
use \Workerman\Events\EventInterface;

Adapterman::init();

# 命令传参解析
$config = paramsAnalysis();

$http_worker = new Worker('http://' . $config['host'] . ':' . $config['port']);
$http_worker->count = $config['workers'];
$http_worker->name = $config['name'];

Worker::$pidFile = dirname(__FILE__) . '/storage/app/workerman' . $config['port'] . '.pid';
Worker::$statusFile = dirname(__FILE__) . '/storage/app/workerman' . $config['port'] . '.status';
Worker::$logFile = dirname(__FILE__) . '/storage/logs/workerman' . $config['port'] . '.log';

$http_worker->onWorkerStart = static function($http_worker) use ($config){
    //  init();
    require __DIR__ . '/start.php';

    /*********************************************
     * 监控文件更新并自动 reload workerman
     * 安装inotify扩展
     *********************************************/
    if (!Worker::$daemonize && $config['port'] == '8020') {
        if (!extension_loaded('inotify')) {
            echo "FileMonitor : Please install inotify extension.\n";
            return;
        }
        global $monitor_dir, $monitor_files;

        // 监控的目录,默认是Applications
        $monitor_dir = [
            realpath(__DIR__ . '/Modules/'),
            realpath(__DIR__ . '/app/'),
            realpath(__DIR__ . '/config/'),
            realpath(__DIR__ . '/database/'),
            realpath(__DIR__ . '/public/'),
            realpath(__DIR__ . '/resources/'),
            realpath(__DIR__ . '/routes/'),
        ];
        // 所有被监控的文件,key为inotify id
        $monitor_files = [realpath(__DIR__ . '/.env')];
        // 初始化inotify句柄
        $http_worker->inotifyFd = inotify_init();
        // 设置为非阻塞
        stream_set_blocking($http_worker->inotifyFd, 0);
        // 递归遍历目录里面的文件
        foreach ($monitor_dir as $val) {
            $dir_iterator = new RecursiveDirectoryIterator($val);
            $iterator = new RecursiveIteratorIterator($dir_iterator);
            foreach ($iterator as $file) {
                // 只监控php文件
                if (pathinfo($file, PATHINFO_EXTENSION) != 'php') {
                    continue;
                }
                // 把文件加入inotify监控,这里只监控了IN_MODIFY文件更新事件
                $wd = inotify_add_watch($http_worker->inotifyFd, $file, IN_MODIFY);
                $monitor_files[$wd] = $file;
            }
        }
        // 监控inotify句柄可读事件
        Worker::$globalEvent->add($http_worker->inotifyFd, EventInterface::EV_READ, 'check_files_change');
    }
};

$http_worker->onMessage = static function($connection, $request){

    $connection->send(run());
};

Worker::runAll();

/**
 * 命令参数解析
 * User: wangmaolin
 * DateTime: 2023/8/22 16:57
 * @return array
 */
function paramsAnalysis(): array
{
    $args = $_SERVER['argv'];
    $data = [
        'port' => 8020,
        'host' => '127.0.0.1',
        'workers' => cpu_count() * 3,
        'name' => '默认项目名',
    ];
    foreach ($args as $arg) {
        if (str_starts_with($arg, '--port=')) {
            $data['port'] = substr($arg, strlen('--port='));
        }
        if (str_starts_with($arg, '--host=')) {
            $data['host'] = substr($arg, strlen('--host='));
        }
        if (str_starts_with($arg, '--workers=')) {
            $data['workers'] = substr($arg, strlen('--workers='));
        }
        if (str_starts_with($arg, '--name=')) {
            $data['name'] = substr($arg, strlen('--name='));
        }
    }
    return $data;
}

/**
 * 监听文件变化,重启服务
 * User: wangmaolin
 * DateTime: 2023/8/22 17:46
 * @param $inotify_fd
 */
function check_files_change($inotify_fd)
{
    global $monitor_files;
    // 读取有哪些文件事件
    $events = inotify_read($inotify_fd);
    if ($events) {
        // 检查哪些文件被更新了
        foreach ($events as $ev) {
            // 更新的文件
            $file = $monitor_files[$ev['wd']];
            //          echo $file . " update and reload\n";
            unset($monitor_files[$ev['wd']]);
            // 需要把文件重新加入监控
            $wd = inotify_add_watch($inotify_fd, $file, IN_MODIFY);
            $monitor_files[$wd] = $file;
        }
        // 给父进程也就是主进程发送reload信号
        posix_kill(posix_getppid(), SIGUSR1);
    }
}

2、start.php

 <?php

use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| Check If The Application Is Under Maintenance
|--------------------------------------------------------------------------
|
| If the application is in maintenance / demo mode via the "down" command
| we will load this file so that any pre-rendered content can be shown
| instead of starting the framework, which could cause an exception.
|
*/

if (file_exists($maintenance = __DIR__ . '/storage/framework/maintenance.php')) {
    require $maintenance;
}

/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| this application. We just need to utilize it! We'll simply require it
| into the script here so we don't need to manually load our classes.
|
*/

require __DIR__ . '/vendor/autoload.php';

/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request using
| the application's HTTP kernel. Then, we will send the response back
| to this client's browser, allowing them to enjoy our application.
|
*/

$app = require_once __DIR__ . '/bootstrap/app.php';

global $kernel;

$kernel = $app->make(Kernel::class);

function run()
{
    global $kernel;

    ob_start();

    $response = $kernel->handle(
        $request = Request::capture()
    )->send();

    $kernel->terminate($request, $response);

    return ob_get_clean();
}

3、服务命令

 # 启动
 /usr/local/php/bin/php /www/test/current/server.php  start --port=8020 --name=项目名

 # 查看状态
  /usr/local/php/bin/php /www/test/current/server.php  status --port=8020

引用链接

[1] https://github.com/joanhey/AdapterMan: https://github.com/joanhey/AdapterMan