此包已被废弃且不再维护。作者建议使用 laragear/preload 包代替。

轻松为您的 Laravel 应用程序创建预加载脚本。

v2.3.2 2022-02-16 18:26 UTC

This package is auto-updated.

Last update: 2022-02-16 18:28:00 UTC


README

请迁移到新包。

Laraload

轻松为您的 Laravel 项目创建 PHP 预加载脚本。

要求

  • Laravel 6.x, 7.x 或 8.x (Lumen 可能 也能使用)
  • PHP 7.4.3, PHP 8.0 或更高版本
  • ext-opcache

此包不强制要求 Opcache 扩展。只需确保在项目的主 PHP 进程中启用它即可。

安装

调用 composer 即可完成。

composer require darkghosthunter/laraload

什么是预加载?这是做什么的?

预加载是 PHP 的一个新功能。它将文件列表“编译”到内存中,从而使应用程序代码运行得更快而不需要预热。为此,它需要在进程启动时读取一个“上传”这些文件的 PHP 脚本。

这允许第一个请求避免冷启动,此时所有脚本都必须由 PHP 在那一刻加载。由于此步骤被移至进程启动时,第一个请求因此变得更,因为所有需要的脚本都已经位于内存中。

此包封装了生成预加载文件的预加载包。一旦生成,您可以将生成的列表指向您的 php.ini

opcache.preload = 'www/app/storage/preload.php';

之后,下一次 PHP 启动时,此文件列表将被预加载。

使用方法

默认情况下,此包会在 storage/preload.php 中每 500 个请求不断重新创建您的预加载脚本。就是这样。但您想了解细节,对吧?

  1. 一个全局可终止的中介检查是否存在非错误响应。
  2. 然后它调用一个自定义的 Condition 类。
  3. 如果 Condition 评估结果为 true,则生成预加载脚本。
  4. 使用生成状态触发 PreloadCalledEvent

配置

有些人可能不会对“默认”行为感到满意。幸运的是,您可以配置自己的方式来生成脚本。

首先发布配置文件

php artisan vendor:publish --provider="DarkGhostHunter\Laraload\LaraloadServiceProvider"

让我们检查配置数组

<?php

return [
    'enable' => env('LARALOAD_ENABLE'),
    'condition' => \DarkGhostHunter\Laraload\Conditions\CountRequests::class,
    'output' =>  storage_path('preload.php'),
    'memory' => 32,
    'use_require' => false,
    'autoload' => base_path('vendor/autoload.php'),
    'ignore-not-found' => true,
];

启用

<?php

return [
    'enable' => env('LARALOAD_ENABLE'),
];

默认情况下,Laraload 会在生产环境中自动启用。您可以使用设置为 truefalse 的环境变量强制启用或禁用它。

LARALOAD_ENABLE=true

条件

<?php

return [
    'condition' => 'App\MyCustomCondition@handle',
];

此包附带一个简单的条件类,该类在每 500 个请求时返回 true,从而触发脚本的生成。

您可以为生成预加载脚本定义自己的条件类。这将在请求处理完毕后由浏览器调用,并由服务容器解决。

条件的调用方式与控制器操作相同:作为可调用的类或使用Class@action表示法。

输出

<?php

return [
    'output' => '/var/www/preloads/my_preload.php',
];

默认情况下,脚本保存在您的存储路径中,但您可以更改文件名和路径,只要PHP有写入权限即可保存。请务必检查您的文件权限。

内存限制

<?php

return [
    'memory' => 64,
];

对于大多数应用程序,32MB作为预加载限制是足够的,但您可能需要根据您的特定项目对其进行微调。

方法

<?php

return [
    'use_require' => true,
    'autoload' => base_path('vendor/autoload.php'),
];

Opcache允许使用require_onceopcache_compile_file()预加载文件。

Laraload使用opcache_compile_file()来更好地管理预加载的文件。一些未解决的链接在启动时可能会输出警告,但没有严重的问题。

使用require_once将“执行”所有文件,在编译之前解析所有链接(导入、父类、特性、接口等),并且可能在不应执行的文件上输出严重错误。根据您的应用程序,您可能希望使用其中一个。

如果您计划使用require_once,请确保您已设置Composer自动加载的正确路径,因为它将用于解决类以及其他文件。

忽略未找到的文件

<?php

return [
    'ignore-not-found' => true,
];

从版本2.1.0开始,默认忽略不存在的文件。这可能适用于由Laravel在运行时创建并由Opcache积极缓存的文件,但在部署时不存在,例如实时外观

您可以根据任何原因禁用此功能,如果任何文件丢失,则将抛出异常,但除非您知道自己在做什么,否则建议保持不变。

包含和排除目录

为了更好地管理,您现在可以使用包含在此包中的Symfony Finder来附加或排除目录中的文件,以获取其中的文件列表,并具有更好的过滤选项。

为此,添加一个array目录,或注册一个接收Symfony Finder实例的回调,以进一步过滤您想要附加或排除的文件。您可以在您的App Service Provider中使用Laravel外观(或注入Laraload)来完成此操作。

use Symfony\Component\Finder\Finder;
use Illuminate\Support\ServiceProvider;
use DarkGhostHunter\Laraload\Facades\Laraload;

class AppServiceProvider extends ServiceProvider
{
    // ...
    
    public function boot()
    {
        Laraload::append(function (Finder $find) {
            $find->in('www/app/vendor/name/package/src')->name('*.php');
        });
        
        Laraload::exclude(function (Finder $find) {
            $find->in('www/app/resources/views')->name('*.blade.php');
        });
    }
}

常见问题解答(FAQ)

  • 我可以禁用Laraload吗?

是的。

  • 我需要重新启动我的PHP服务器来获取更改吗?

绝对需要。生成脚本是不够的,如果脚本路径为空或PHP进程本身没有完全重新启动,则PHP不会获取更改。您可以使用CRON或其他方式安排服务器重启。

  • 当我使用它时,包返回错误!

检查您是否使用的是最新的PHP稳定版本(关键),并且Opcache已启用。此外,请检查您的存储目录是可写的。

作为一个安全的赌注,您可以使用位于darkghosthunter/preloader/helpers/safe-preloader.php中的安全预加载脚本,并调试错误。

如果您确定这是一个由包引起的错误,请打开一个issue,包含完整细节和堆栈跟踪。如果这是一个由预加载本身引起的问题,请在那里提出问题

  • 为什么我不能使用类似 php artisan laraload:generate 的命令?比如使用一个 监听器调度器 吗?

当使用 PHP CLI 时,Opcache 不会被启用,如果启用了,它将收集错误的统计信息。您必须让实时应用程序在需要时自动生成列表。

  • 这会排除包本身吗?

不会的:因为底层 Preloader 包可能不会被频繁请求,所以是否排除它并不重要。Laraload 中的文件也不会被排除在列表之外,因为这些文件是触发 Preloader 所必需的,而不会影响性能。

  • 我已经激活了 Laraload,但我的应用程序仍然感觉不够 。怎么回事?

Laraload 会创建一个预加载脚本,但 不会将脚本加载到 Opcache 中。一旦脚本被生成,您必须将其包含在您的 php.ini 文件中 - 目前没有其他方法可以做到这一点。这将只在 PHP 进程启动时生效。

如果您仍然 觉得应用程序运行缓慢,请记住对您的应用程序进行基准测试,缓存配置和视图,检查数据库查询和 API 调用,并排队执行昂贵的逻辑等。您还可以在 RoadRunner 上使用 Laravel Octane

  • 列表是如何创建的?

基本上:按访问次数降序排列的最频繁访问的文件。每个文件都会消耗内存,所以当文件达到一定的内存限制(默认为 32MB)时,列表会进行 软切割

  • 你说 "软切割",为什么是这样?

每个文件都是通过 opcache_compile_file() 加载的。如果最后一个文件是一个包含列表外链接的类,PHP 将发出一些警告,这是正常且预期的,但如果这些文件之前没有被添加,它不会编译链接的文件。

  • 我可以将项目中的所有文件都放进去吗?

您不应该这样做。包含应用程序的所有文件与仅包含最常请求的文件相比,可能效果不明显。您始终可以自己基准测试应用程序以证明这对于您的情况是错误的。

  • 我可以使用闭包(Closure)作为条件吗?

不,您必须使用您的默认条件类或您自己的类,或者使用 Class@method 语法。

  • 我可以禁用中间件吗?或者只检查 XXX 状态?

不行。如果您需要完全控制,请直接使用 Preloader 包

  • 中间件在单元测试中工作吗?

不行。当应用程序在单元测试环境中运行时,中间件不会被注册。

  • 我如何知道预加载脚本是否成功生成?

当预加载脚本被调用时,您将收到一个包含编译状态(成功为 true,失败为 false)的 PreloadCalledEvent 实例。您可以通过 添加监听器 来发送电子邮件或 Slack 通知。

如果存在问题,应用程序的日志记录器将捕获异常。

  • 为什么我现在需要使用回调来追加/排除文件,而不是一个简单的文件数组?

这个新版本使用 Preloader 2,它为处理目录内的文件提供了更大的灵活性。这种方法与直接发出文件数组不兼容,但长期来看更方便。考虑到追加和排除文件大多需要精确度,因此决定将其保留为方法调用以提供这种灵活性。

  • 我如何更改默认条件的访问次数、缓存或缓存键?

虽然我鼓励您创建自己的条件,但您可以通过在AppServiceProvider.php文件中的register()方法下添加一个容器事件来轻松地更改它们。

$this->app->when(\DarkGhostHunter\Laraload\Conditions\CountRequests::class)
     ->needs('$hits')
     ->give(1500);

许可证

本软件包的许可证由MIT许可证授权。