php - Laravel 8 : QueueManager. php:156 类型为空的数组偏移量/配置redis

标签 php laravel symfony redis queue

我要设置RedisLaravel Horizon .尽管我已经正确设置了所有内容(我假设),但我收到了一个非常奇怪的错误。 Laravel告诉我它是 Trying to access array offset on value of type nullvendor/laravel/framework/src/Illuminate/Queue/QueueManager.php:156线路156是第一个返回行:

/**
* Resolve a queue connection.
*
* @param  string  $name
* @return \Illuminate\Contracts\Queue\Queue
*/
protected function resolve($name)
{
    $config = $this->getConfig($name);

    return $this->getConnector($config['driver']) // <-- This line
                    ->connect($config)
                    ->setConnectionName($name);
}
所以,我假设 Laravel无法访问 $config['driver'] .但是当我做一个 dd$config我得到以下信息:
array:5 [
  "driver" => "redis"
  "connection" => "default"
  "queue" => "default"
  "retry_after" => 90
  "block_for" => null
]
所以,它是 不可能 那个driver是空的,因为如您所见 driver设置为 redis .你们知道为什么Laravel不能 access array offset on value of type null ?
我已安装 phpredis , Redis database还有 Laravel Horizon .当我尝试访问我的 /horizon 时我得到与上面相同的错误。phpredis安装正确。我已添加 extension=redis.so到我的 php.ini当我执行 php -r "if (new Redis() == true){ echo \"\r\n OK \r\n\"; }"在我的命令行中,我也得到了 OK .所以,它不能是 phpredis .
我的 Redis database也在工作:
$ redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>
而且我的配置也是正确的。这是我的 .env (只是一些条目):
APP_ENV=local
APP_DEBUG=true

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=password

BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=redis
SESSION_DRIVER=file
SESSION_LIFETIME=120

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
这是我的 config/queue.php :
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Default Queue Connection Name
    |--------------------------------------------------------------------------
    |
    | Laravel's queue API supports an assortment of back-ends via a single
    | API, giving you convenient access to each back-end using the same
    | syntax for every one. Here you may define a default connection.
    |
    */

    'default' => env('QUEUE_CONNECTION', 'sync'),

    /*
    |--------------------------------------------------------------------------
    | Queue Connections
    |--------------------------------------------------------------------------
    |
    | Here you may configure the connection information for each server that
    | is used by your application. A default configuration has been added
    | for each back-end shipped with Laravel. You are free to add more.
    |
    | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
    |
    */

    'connections' => [

        'sync' => [
            'driver' => 'sync',
        ],

        'database' => [
            'driver' => 'database',
            'table' => 'jobs',
            'queue' => 'default',
            'retry_after' => 90,
        ],

        'beanstalkd' => [
            'driver' => 'beanstalkd',
            'host' => 'localhost',
            'queue' => 'default',
            'retry_after' => 90,
            'block_for' => 0,
        ],

        'sqs' => [
            'driver' => 'sqs',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
            'queue' => env('SQS_QUEUE', 'your-queue-name'),
            'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
        ],

        'redis' => [
            'driver' => 'redis',
            'connection' => 'default',
            'queue' => env('REDIS_QUEUE', 'default'),
            'retry_after' => 90,
            'block_for' => null,
        ],

    ],

    /*
    |--------------------------------------------------------------------------
    | Failed Queue Jobs
    |--------------------------------------------------------------------------
    |
    | These options configure the behavior of failed queue job logging so you
    | can control which database and table are used to store the jobs that
    | have failed. You may change them to any database / table you wish.
    |
    */

    'failed' => [
        'driver' => env('QUEUE_FAILED_DRIVER', 'database'),
        'database' => env('DB_CONNECTION', 'mysql'),
        'table' => 'failed_jobs',
    ],

];
我的 config/horizon.php
<?php

use Illuminate\Support\Str;

return [

    /*
    |--------------------------------------------------------------------------
    | Horizon Domain
    |--------------------------------------------------------------------------
    |
    | This is the subdomain where Horizon will be accessible from. If this
    | setting is null, Horizon will reside under the same domain as the
    | application. Otherwise, this value will serve as the subdomain.
    |
    */

    'domain' => env('HORIZEN_DOMAIN', null),

    /*
    |--------------------------------------------------------------------------
    | Horizon Path
    |--------------------------------------------------------------------------
    |
    | This is the URI path where Horizon will be accessible from. Feel free
    | to change this path to anything you like. Note that the URI will not
    | affect the paths of its internal API that aren't exposed to users.
    |
    */

    'path' => env('HORIZEN_PATH', 'horizon'),

    /*
    |--------------------------------------------------------------------------
    | Horizon Redis Connection
    |--------------------------------------------------------------------------
    |
    | This is the name of the Redis connection where Horizon will store the
    | meta information required for it to function. It includes the list
    | of supervisors, failed jobs, job metrics, and other information.
    |
    */

    'use' => 'default',

    /*
    |--------------------------------------------------------------------------
    | Horizon Redis Prefix
    |--------------------------------------------------------------------------
    |
    | This prefix will be used when storing all Horizon data in Redis. You
    | may modify the prefix when you are running multiple installations
    | of Horizon on the same server so that they don't have problems.
    |
    */

    'prefix' => env(
        'HORIZON_PREFIX',
        Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:'
    ),

    /*
    |--------------------------------------------------------------------------
    | Horizon Route Middleware
    |--------------------------------------------------------------------------
    |
    | These middleware will get attached onto each Horizon route, giving you
    | the chance to add your own middleware to this list or change any of
    | the existing middleware. Or, you can simply stick with this list.
    |
    */

    'middleware' => ['web'],

    /*
    |--------------------------------------------------------------------------
    | Queue Wait Time Thresholds
    |--------------------------------------------------------------------------
    |
    | This option allows you to configure when the LongWaitDetected event
    | will be fired. Every connection / queue combination may have its
    | own, unique threshold (in seconds) before this event is fired.
    |
    */

    'waits' => [
        'redis:default' => 60,
    ],

    /*
    |--------------------------------------------------------------------------
    | Job Trimming Times
    |--------------------------------------------------------------------------
    |
    | Here you can configure for how long (in minutes) you desire Horizon to
    | persist the recent and failed jobs. Typically, recent jobs are kept
    | for one hour while all failed jobs are stored for an entire week.
    |
    */

    'trim' => [
        'recent' => 60,
        'pending' => 60,
        'completed' => 60,
        'recent_failed' => 10080,
        'failed' => 10080,
        'monitored' => 10080,
    ],

    /*
    |--------------------------------------------------------------------------
    | Metrics
    |--------------------------------------------------------------------------
    |
    | Here you can configure how many snapshots should be kept to display in
    | the metrics graph. This will get used in combination with Horizon's
    | `horizon:snapshot` schedule to define how long to retain metrics.
    |
    */

    'metrics' => [
        'trim_snapshots' => [
            'job' => 24,
            'queue' => 24,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Fast Termination
    |--------------------------------------------------------------------------
    |
    | When this option is enabled, Horizon's "terminate" command will not
    | wait on all of the workers to terminate unless the --wait option
    | is provided. Fast termination can shorten deployment delay by
    | allowing a new instance of Horizon to start while the last
    | instance will continue to terminate each of its workers.
    |
    */

    'fast_termination' => false,

    /*
    |--------------------------------------------------------------------------
    | Memory Limit (MB)
    |--------------------------------------------------------------------------
    |
    | This value describes the maximum amount of memory the Horizon master
    | supervisor may consume before it is terminated and restarted. For
    | configuring these limits on your workers, see the next section.
    |
    */

    'memory_limit' => 64,

    /*
    |--------------------------------------------------------------------------
    | Queue Worker Configuration
    |--------------------------------------------------------------------------
    |
    | Here you may define the queue worker settings used by your application
    | in all environments. These supervisors and settings handle all your
    | queued jobs and will be provisioned by Horizon during deployment.
    |
    */

    'defaults' => [
        'supervisor-1' => [
            'connection' => 'redis',
            'queue' => ['default'],
            'balance' => 'auto',
            'maxProcesses' => 1,
            'memory' => 128,
            'tries' => 1,
            'nice' => 0,
        ],
    ],

    'environments' => [
        'production' => [
            'supervisor-1' => [
                'connection' => 'redis',
                'queue' => ['default'],
                'balance' => 'simple',
                'processes' => 10,
                'tries' => 2,
                'timeout' => 60 * 60,
            ],
            'mailcoach-general' => [
                'connection' => 'mailcoach-redis',
                'queue' => ['mailcoach', 'mailcoach-feedback', 'send-mail'],
                'balance' => 'auto',
                'processes' => 10,
                'tries' => 2,
                'timeout' => 60 * 60,
            ],
            'mailcoach-heavy' => [
                'connection' => 'mailcoach-redis',
                'queue' => ['send-campaign'],
                'balance' => 'auto',
                'processes' => 3,
                'tries' => 1,
                'timeout' => 60 * 60,
            ],
        ],

        'local' => [
            'supervisor-1' => [
                'connection' => 'redis',
                'queue' => ['default'],
                'balance' => 'simple',
                'processes' => 10,
                'tries' => 2,
                'timeout' => 60 * 60,
            ],
            'mailcoach-general' => [
                'connection' => 'mailcoach-redis',
                'queue' => ['mailcoach', 'mailcoach-feedback', 'send-mail'],
                'balance' => 'auto',
                'processes' => 10,
                'tries' => 2,
                'timeout' => 60 * 60,
            ],
            'mailcoach-heavy' => [
                'connection' => 'mailcoach-redis',
                'queue' => ['send-campaign'],
                'balance' => 'auto',
                'processes' => 3,
                'tries' => 1,
                'timeout' => 60 * 60,
            ],
        ],
    ],
];
任何人都知道为什么我会收到此错误?
我正在处理 php 7.4.16 , 10.5.6-MariaDB , redis-cli 6.2.1并在 Laravel Framework 8.32.1 .所以,一切都在最新版本上。
我将不胜感激任何形式的帮助!
亲切的问候

最佳答案

  • 编辑:我只是想到了一些东西……您的 Redis 设置运行正常,对吗?我的意思是当你做 $redisclient->setex('test', 123, 'value');当您执行 keys test 时,它会立即显示在您的 redis-cli 中?

  • 好的,让我们来看看我将如何设置它并解决这个问题。
    我认为您的错误处于整个过程的“最后阶段”,让我们首先检查队列是否运行正常等。
    所以我正在使用 Docker 容器,但这应该无关紧要。
    我认为 Horizo​​n 非常好,尤其是与使用默认的“queue:work”相比,因为您可以访问仪表板和监控。
    正如我所说,我认为使用监督服务来运行队列 worker 是一个好主意,也如 Laravel 文档中所述:
    To keep the queue:work process running permanently in the background, you should use a process monitor such as Supervisor to ensure that the queue worker does not stop running.
    
    真正的原因是它会在出现错误时自动重新启动您的队列等。
    所以下面我经历了一些,可能是主管过多的东西......
    所以运动部件是:
  • 主管 > 队列工作进程:地平线
  • Redis
  • Laravel 应用

  • 正如我所说,我在我的 Docker PHP-FPM 容器中运行 Supervisor ,它依次运行 cron、Horizo​​n 和 PHP-FPM,但在您的情况下,您可以像这样使用 apt-get 安装 Supervisor https://laravel.com/docs/8.x/horizon#installing-supervisor让它运行地平线。
    这样做我还可以指出将创建的日志文件,它可能会告诉我们更多细节:)
    确保在安装 supervisor 并将 example-hotizon.conf 配置文件添加到您的 conf.d 目录后,您执行 supervisor reread (重新读取配置文件)然后是 supervisor update进程配置更改。
    ====== 启动主管 ======
    我的地平线主管配置:
    [program:example-horizon]
    process_name=%(program_name)s
    command=php /var/www/example.com/artisan horizon
    autostart=true
    autorestart=true
    user=www-data
    redirect_stderr=true
    stdout_logfile=/var/www/example.com/storage/logs/horizon.log
    # Kill the job after "stopwaitsecs" secs, make sure this is greater than the longest running job
    stopwaitsecs=600
    
    那我觉得你可以做supervisord -c /etc/supervisor/supervisord.conf随着我的 supervisord.conf 像这样,我已经取出了我的 Cron 和 PHP-FPM 配置......:
    ; http://supervisord.org/configuration.html
    
    [unix_http_server]
    file=/var/run/supervisor.sock               ; (the path to the socket file)
    chmod=0700                                  ; sockef file mode (default 0700)
    
    [supervisord]
    nodaemon=true                               ; This keeps the Docker container alive (in the foreground)
    user=root                                   ; default user
    logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
    pidfile=/var/run/supervisord.pid            ; (supervisord pidfile;default supervisord.pid) 
    childlogdir=/var/log/supervisor             ; ('AUTO' child log dir, default $TEMP)
    
    ; the below section must remain in the config file for RPC
    ; (supervisorctl/web interface) to work, additional interfaces may be
    ; added by defining them in separate rpcinterface: sections
    [rpcinterface:supervisor]
    supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 
    
    [supervisorctl]
    serverurl=unix:///var/run/supervisor.sock   ; use a unix:// URL  for a unix socket 
    
    ; The [include] section can just contain the "files" setting.  This
    ; setting can list multiple files (separated by whitespace or
    ; newlines).  It can also contain wildcards.  The filenames are
    ; interpreted as relative to this file.  Included files *cannot*
    ; include files themselves.
    [include]
    files = /etc/supervisor/conf.d/*.conf
    
    我想你也已经发布了 Horizo​​n 吧? php artisan horizon:publish在你做了之后 php artisan horizon:install我相信使用仪表板功能。
    让我们通过留意 no 来测试这将输出什么:
  • 我们的主管控制台
  • 我们的日志文件/var/www/example.com/storage/logs/horizo​​n.log(在 horizo​​n.conf 中设置)

  • 所以让我们从我们的主管控制台开始。
    运行 supervisorctl从您的命令提示符,您将看到正在运行的进程,希望您的示例水平进程实际上是“正在运行”而不是“已停止”或类似的。
    您还可以通过从 supervisorctl 运行 tail 来检查日志,所以 tail example-horizon并检查该输出。
    supervisor log example
    在我的情况下 supervisorctl status我有:
    # supervisorctl status
    cron                             RUNNING   pid 8, uptime 3 days, 22:09:07
    example-horizon                  RUNNING   pid 10, uptime 3 days, 22:09:07
    php-fpm                          RUNNING   pid 9, uptime 3 days, 22:09:07
    
    ====== 最终主管 ======
    ====== 启动Redis ======
    然后当主管部分工作时,我假设你的 Redis 配置在你的 .env 中没问题,但你可以做的是检查你的 Redis 是否有 Horizo​​n 队列键:
    Redis output
    我的被​​称为“horizo​​n_LW1_xxx”,因为我在 Horizo​​n 配置中使用了“horizo​​n_LW1”作为地平线的前缀 config/horizon.php ,我的看起来像:
    'prefix' => env(
            'HORIZON_PREFIX',
            Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:'
        ),
    
    如果你的 Redis 中没有这个,我们应该先解决这个问题......
    ====== 结束Redis ======
    ====== 配置/horizo​​n.php ======
    只是我的本地地平线配置取决于我的环境“HOZIRON_QUEUE_LOCAL”,这是我的不同队列:HOZIRON_QUEUE_LOCAL=prio1,prio2,email,default
    'local' => [
                'supervisor-it' => [
                    'queue' => explode(',', env('HOZIRON_QUEUE_LOCAL', 'default')),
                    'maxProcesses' => 23,
                    'memory' => 100,
                ],
            ],
    
    让我们向队列中启动一项工作,监视您的主管“tail example-horizo​​n”(storage/logs/horizo​​n.log)、您的 Laravel 日志(storage/logs/laravel.log)和您的 Redis 队列。
    抱歉,这有点像小说,但基本上:
  • 安装主管
  • 通过主管运行 Horizo​​n 队列
  • 检查 Redis key
  • 检查日志(主管,laravel)

  • 让我知道上述情况如何,因为我相信它们是良好 Horizo​​n 设置的“根源”。
    然后我们可以继续下一步,以防还没有成功。

    关于php - Laravel 8 : QueueManager. php:156 类型为空的数组偏移量/配置redis,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66636264/

    相关文章:

    php - 在配置文件中使用/opt/v8,而不是/usr

    php - Laravel 5.6 如何逐行读取文本文件

    php - 如何在 CentOS 6.x 上更新 PHP 和安装 ICU 库

    PHP脚本添加新记录,但字段都是空白

    php - 将 French_CI_AS (ASCII) 转换为 UTF8

    php - 在 Laravel 7x 上找不到特征 'Illuminate\Foundation\Auth\AuthenticatesUsers'

    php - 如何在 Silex 中为一个请求定义多个路由?

    php - 无法选择使用 jQuery Ajax 调用加载的 div 内的元素

    php - 如何通过表单提交更新 php 文件中的变量?比如静态密码

    mongodb - Symfony2 和 MongoDB 注释/映射无法识别