Laravel Octane 使用swoole来加速你的项目

简介

Laravel Octane通过使用功能强大的应用程序服务器(包括SwooleRoadRunner )为应用程序提供服务,从而增强了应用程序的性能。Octane引导您的应用程序一次,将其保存在内存中,然后以超音速提供请求。
官方地址

安装

可以通过Composer软件包管理器安装Octane:

composer require laravel/octane

安装Octane之后,您可以执行octane:install Artisan命令,该命令会将Octane的配置文件安装到您的应用程序中:

php artisan octane:install

安装条件

  • PHP8+
  • laravel v.8.37+

RoadRunner

RoadRunner由使用Go构建的RoadRunner二进制文件提供动力。首次启动基于RoadRunner的Octane服务器时,Octane将为您下载并安装RoadRunner二进制文件。

RoadRunner Via Laravel Sail

RoadRunner具体使用可以查看原文。

Swoole安装

pecl install swoole
启动你的服务

可以通过octane:startArtisan命令启动Octane服务器。默认情况下,此命令将利用server应用程序octane配置文件的配置选项指定的服务器:

php artisan octane:start
设置应用HTTPS.配置
OCTANE_HTTPS=false
设置启动服务的容器
OCTANE_SERVER=swoole
应用代码热加载
php artisan octane:start --watch
  • 注意
    使用该命令之前,应该确保本地安装了Node 服务.您应该在您的project:library中安装Chokidar 文件监视库:
npm install --save-dev chokidar

您可以使用watch应用程序的config/octane.php配置文件中的配置选项来配置应监视的目录和文件。

指定worker进程数

默认情况下,Octane将为您的计算机提供的每个CPU内核启动一个应用程序请求工作程序。然后,这些工作程序将在进入您的应用程序时用于处理传入的HTTP请求。您可以--workers在调用octane:start命令时手动指定要使用该选项的工人数量:

php artisan octane:start --workers=4

如果使用的是Swoole应用程序服务器,则还可以指定要启动的“任务工作者”数量:

php artisan octane:start --workers=4 --task-workers=6
指定最大的请求数
php artisan octane:start --max-requests=250
服务重启

您可以使用以下octane:reload命令正常重启Octane服务器的应用程序工作程序。通常,应在部署后执行此操作,以便将新部署的代码加载到内存中并用于处理后续请求:

php artisan octane:reload
服务停止

您可以使用octane:stopArtisan命令停止Octane服务器:

php artisan octane:stop
查看服务状态
php artisan octane:status
Octane 依赖注入

由于Octane会一次引导您的应用程序并在处理请求时将其保存在内存中,因此在构建应用程序时应注意一些注意事项。例如,您的应用程序服务提供商的registerand boot方法仅在请求启动程序最初启动时执行一次。在后续请求中,相同的应用程序实例将被重用。

有鉴于此,在将应用程序服务容器或请求注入到任何对象的构造函数中时,应格外小心。这样,该对象可能具有旧版本的容器或后续请求中的请求。

Octane将自动处理重置请求之间的任何第一方框架状态。但是,Octane并不总是知道如何重置应用程序创建的全局状态。因此,您应该了解如何以Octane友好的方式构建应用程序。下面,我们将讨论使用辛烷值时可能引起问题的最常见情况。

容器注入

通常,应避免将应用程序服务容器或HTTP请求实例注入其他对象的构造函数中。例如,以下绑定将整个应用程序服务容器注入到作为单例绑定的对象中:

use App\Service;

/**
 * Register any application services.
 *
 * @return void
 */
public function register()
{
    $this->app->singleton(Service::class, function ($app) {
        return new Service($app);
    });
}

在此示例中,如果Service在应用程序启动过程中解析了该实例,则该容器将被注入到服务中,并且该Service实例将在后续请求中保留该容器。对于您的特定应用程序,这可能不是问题;但是,这可能导致容器意外丢失在引导周期后期或后续请求中添加的绑定。

解决方法是,您可以停止将绑定注册为单例,也可以将容器解析器闭包注入始终解析当前容器实例的服务中:

use App\Service;
use Illuminate\Container\Container;

$this->app->bind(Service::class, function ($app) {
    return new Service($app);
});

$this->app->singleton(Service::class, function () {
    return new Service(fn () => Container::getInstance());
});

全局app帮助器和Container::getInstance()方法将始终返回应用程序容器的最新版本。

请求注入

通常,应避免将应用程序服务容器或HTTP请求实例注入其他对象的构造函数中。例如,以下绑定将整个请求实例注入到作为单例绑定的对象中:

use App\Service;

/**
 * Register any application services.
 *
 * @return void
 */
public function register()
{
    $this->app->singleton(Service::class, function ($app) {
        return new Service($app['request']);
    });
}

在此示例中,如果Service在应用程序启动过程中解析了实例,则HTTP请求将被注入到服务中,并且该Service实例将在后续请求中保留相同的请求。因此,所有标头,输入和查询字符串数据以及所有其他请求数据都将不正确。

解决方法是,您可以停止将绑定注册为单例,或者可以将请求解析程序闭包注入始终解析当前请求实例的服务中。或者,最推荐的方法只是在运行时将对象需要的特定请求信息传递给对象的方法之一:

use App\Service;

$this->app->bind(Service::class, function ($app) {
    return new Service($app['request']);
});

$this->app->singleton(Service::class, function ($app) {
    return new Service(fn () => $app['request']);
});

// Or...

$service->method($request->input('name'));

全局request帮助程序将始终返回应用程序当前正在处理的请求,因此可以在您的应用程序中安全使用。

配置文件注入

通常,应避免将配置实例注入其他对象的构造函数中。例如,以下绑定将配置注入到作为单例绑定的对象中:

use App\Service;

/**
 * Register any application services.
 *
 * @return void
 */
public function register()
{
    $this->app->singleton(Service::class, function ($app) {
        return new Service($app->make('config'));
    });
}

在此示例中,如果配置值在两次请求之间更改,则该服务将无法访问新值,因为它取决于原始存储库实例。

解决方法是,您可以停止将绑定注册为单例,或者可以将配置存储库解析器闭包注入到该类中:

use App\Service;
use Illuminate\Container\Container;

$this->app->bind(Service::class, function ($app) {
    return new Service($app->make('config'));
});

$this->app->singleton(Service::class, function () {
    return new Service(fn () => Container::getInstance()->make('config'));
});

全局config将始终返回配置的最新版本,因此可以在您的应用程序中安全使用。

管理内存泄漏

请记住,Octane在两次请求之间将您的应用程序保留在内存中;因此,将数据添加到静态维护的阵列将导致内存泄漏。例如,由于对应用程>序的每个请求将继续向静态$data数组添加数据,因此以下控制器发生内存泄漏:

se App\Service;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return void
 */
public function index(Request $request)
{
    Service::$data[] = Str::random(10);

    // ...
}
并发任务
  • 提示该功能需要使用Swoole

使用Swoole时,您可以通过轻量级后台任务同时执行操作。您可以使用Octane:: tick concurrently方法完成此操作。您可以将此方法与PHP数组解>构相结合,以检索每个操作的结果:


use App\User;
use App\Server;
use Laravel\Octane\Facades\Octane;

[$users, $servers] = Octane::concurrently([
    fn () => User::all(),
    fn () => Server::all(),
]);

由Octane处理的并发任务利用Swoole的“task workers”,并在与传入请求完全不同的过程中执行。可用于处理并发任务的工作者数量由--task-workers命令上的octane:start指令确定:

php artisan octane:start --workers=4 --task-workers=6
定时器 & 时间间隔
  • 提示该功能需要使用Swoole

使用Swoole时,您可以注册将在每指定的秒数内执行的“tick”操作。您可以通过tick方法注册“ tick”回调。提供给该tick方法的第一个参数应该是代表股票行情指示器名称的字符串。第二个参数应该是可调用的,它将在指定的时间间隔被调用。

在此示例中,我们将注册一个闭包,每10秒调用一次。通常,tick应在boot应用程序的服务提供者之一的方法内调用该方法:

Octane::tick('simple-ticker', fn () => ray('Ticking...'))
       ->seconds(10);

使用该immediate方法,您可以指示Octane在Octane服务器最初启动时立即调用tick回调,此后每隔N秒:

Octane::tick('simple-ticker', fn () => ray('Ticking...'))
        ->seconds(10)
        ->immediate();
Octane 缓存

这功能依赖于Swoole

使用Swoole时,您可以利用Octane缓存驱动程序,该驱动程序提供每秒高达200万次操作的读写速度。因此,对于需要从其缓存层实现极高读/写速度的应用程序而言,此缓存驱动程序是一个绝佳选择。
该缓存驱动程序由Swoole表提供动力。缓存中存储的所有数据对服务器上的所有工作人员均可用。但是,重新启动服务器后,将刷新缓存的数据:

Cache::store('octane')->put('framework', 'Laravel', 30);
缓存间隔

除了Laravel缓存系统提供的典型方法外,Octane缓存驱动程序还具有基于间隔的缓存。这些缓存将按指定的时间间隔自动刷新,并应使用boot您的应用程序的服务提供商之一的方法进行注册。例如,以下缓存将每五秒钟刷新一次:

use Illuminate\Support\Str;

Cache::store('octane')->interval('random', function () {
    return Str::random(10);
}, seconds: 5)
进程间共享内存 (table)

使用Swoole时,您可以定义自己的任意Swoole表并与之交互。Swoole表提供了极高的性能吞吐量,并且服务器上的所有工作人员都可以访问这些表中的数据。但是,重新启动服务器后,其中的数据将丢失。

表应在tables应用程序的octane配置文件的配置数组中定义。已经为您配置了一个示例表,该表最多允许1000行。可以通过在列类型之后指定列大小来配置字符串列的最大大小,如下所示:

'tables' => [
    'example:1000' => [
        'name' => 'string:1000',
        'votes' => 'int',
    ],
],

要访问表,可以使用以下Octane::table方法:


use Laravel\Octane\Facades\Octane;

Octane::table('example')->set('uuid', [
    'name' => 'Nuno Maduro',
    'votes' => 1000,
]);

return Octane::table('example')->get('uuid');

通过Swoole table 支持的列类型:stringint,和 float

翻译地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现热更新,可以使用 Swoole 的 Table、Redis 等实现进程间通信,监听某个特定端口,当接收到热更新的命令时,通过进程间通信将新代码的路径传递给工作进程,执行重载代码的操作。 具体实现步骤如下: 1.在进程启动时创建一个 Table,用于存储需要热更新的文件路径,如下所示: ```php $table = new Swoole\Table(1024); $table->column('path', Swoole\Table::TYPE_STRING, 256); $table->create(); ``` 2.在 Swoole Server 中监听一个特定端口,等待接收热更新命令,如下所示: ```php $server = new Swoole\Http\Server('0.0.0.0', 9501); $server->on('request', function ($request, $response) use ($table) { // 判断是否为热更新命令 if ($request->post['cmd'] === 'hot-update') { // 获取需要更新的文件路径 $path = $request->post['path']; // 将文件路径存储到 Table 中 $table->set('file', ['path' => $path]); // 返回更新成功的响应 $response->end(json_encode(['code' => 0, 'msg' => 'ok'])); } else { // 其他请求处理逻辑 // ... } }); $server->start(); ``` 3.在工作进程中监听 Table 的变化,如下所示: ```php $table->on('table', function ($table, $type, $key, $value) use ($server) { if ($type === Swoole\Table::TYPE_SET && $key === 'file') { // 获取需要更新的文件路径 $path = $value['path']; // 执行重载代码的操作 // ... // 重启工作进程 $server->reload(); } }); ``` 当接收到热更新命令时,会将需要更新的文件路径存储到 Table 中,工作进程会监听 Table 的变化,一旦发生变化就会执行重载代码的操作,并重启工作进程,从而实现热更新。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值