尝试 pushRaw 时出现 AMQP 错误:未定义的索引:名称

AMQP error while attempting pushRaw: Undefined index: name

我正在将 Laravel 从 5.4.* 升级到 5.5.0。 RabbitMQ 在 5.4 中工作得非常好,但现在当我尝试 运行 使用队列的功能时,它在日志中显示以下错误:

AMQP error while attempting pushRaw: Undefined index: name

日志中没有其他信息。这是我的 .env:

RABBITMQ_HOST=localhost
RABBITMQ_PORT=5672
RABBITMQ_VHOST=/
RABBITMQ_LOGIN=test
RABBITMQ_PASSWORD=test
RABBITMQ_QUEUE=reporting
RABBITMQ_JOB_QUEUE=dev

这是我的配置 queue.php:

'worker' => [
    'driver' => 'rabbitmq',
    'factory_class' => Enqueue\AmqpLib\AmqpConnectionFactory::class,
    'host' => env('RABBITMQ_HOST'),
    'port' => env('RABBITMQ_PORT'),
    'vhost' => env('RABBITMQ_VHOST'),
    'login' => env('RABBITMQ_LOGIN'),
    'password' => env('RABBITMQ_PASSWORD'),
    'queue' => env('RABBITMQ_JOB_QUEUE'),

    'options' => [
        'exchange' => [
            'name' => env('RABBITMQ_EXCHANGE_NAME', null),
            /*
            * Determine if exchange should be created if it does not exist.
            */
            'declare' => env('RABBITMQ_EXCHANGE_DECLARE', true),
            /*
            * Read more about possible values at https://www.rabbitmq.com/tutorials/amqp-concepts.html
            */
            'type' => env('RABBITMQ_EXCHANGE_TYPE', \Interop\Amqp\AmqpTopic::TYPE_DIRECT),
            'passive' => env('RABBITMQ_EXCHANGE_PASSIVE', false),
            'durable' => env('RABBITMQ_EXCHANGE_DURABLE', true),
            'auto_delete' => env('RABBITMQ_EXCHANGE_AUTODELETE', false),
            'arguments' => env('RABBITMQ_EXCHANGE_ARGUMENTS'),
        ],
        'queue' => [
            /*
            * Determine if queue should be created if it does not exist.
            */
            'declare' => env('RABBITMQ_QUEUE_DECLARE', true),
            /*
            * Determine if queue should be binded to the exchange created.
            */
            'bind' => env('RABBITMQ_QUEUE_DECLARE_BIND', true),
            /*
            * Read more about possible values at https://www.rabbitmq.com/tutorials/amqp-concepts.html
            */
            'passive' => env('RABBITMQ_QUEUE_PASSIVE', false),
            'durable' => env('RABBITMQ_QUEUE_DURABLE', true),
            'exclusive' => env('RABBITMQ_QUEUE_EXCLUSIVE', false),
            'auto_delete' => env('RABBITMQ_QUEUE_AUTODELETE', false),
            'arguments' => env('RABBITMQ_QUEUE_ARGUMENTS'),
        ],
    ],
],

这是 composer.jsonRabbitMQ 的版本:

"vladimir-yuldashev/laravel-queue-rabbitmq": "6.0.0",

我的 Laravel 版本是 5.5.0。我试图推入队列的任务是:

\Mail::to($user->email)->queue(new MailPriceRequest($priceRequests));

这里出了什么问题?有帮助吗?

编辑:

这里是 MailPriceRequest class:

class MailPriceRequest extends Mailable implements ShouldQueue
{
    use Queueable, SerializesModels;

    /**
     * @var
     */
    public $title;

    /**
     * @var
     */
    public $items;

    /**
     * @var array
     */
    public $groupedPriceRequests = [];

    /**
     * @var
     */
    public $grouped;

    /**
     * @var string
     */
    public $groupName = '';

    /**
     * @var
     */
    public $emailSubject;

    /**
     * MailPriceRequest constructor.
     * @param $transportOrders
     */
    public function __construct($priceRequests)
    {
        $this->items = $priceRequests;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        $this->setPriceRequests();
        $this->setTitle();
        $this->setGrouped();
        $this->setSubject();
        return $this->subject($this->emailSubject)->view('emails.price-requests.overview');
    }

    /**
     * @return $this
     */
    public function setSubject()
    {
        $this->emailSubject = $this->getOrderNumber();

        return $this;
    }

    /**
     * @return $this
     */
    public function setGrouped()
    {
        $this->grouped = $this->groupedPriceRequests;

        return $this;
    }

    /**
     * @return $this
     */
    public function setTitle()
    {
        $this->title = 'title';

        return $this;
    }

    /**
     * @return $this
     */
    public function setPriceRequests()
    {
        $this->groupByCarrier();

        return $this;
    }

    /**
     * @return $this
     */
    public function groupByCarrier()
    {
        $transformer = \App::make(PriceRequestMailTransformer::class);
        foreach ($this->items as $priceRequest) {
            if (!array_key_exists($priceRequest->carrier_name, $this->groupedPriceRequests)) {
                $this->groupedPriceRequests[$priceRequest->carrier_name] = [
                    'price_requests' => []
                ];
            }
            $transformed = $transformer->transform($priceRequest);

            $this->groupedPriceRequests[$priceRequest->carrier_name]['price_requests'][] = $transformed;
        }

        return $this;
    }

    /**
     * @return string|null
     */
    private function getOrderNumber()
    {
        if (count($this->items) > 1) {
            return ' - ' . $this->items->first()->order_number . ' - and more references';
        }

        if (count($this->items) == 1) {
            return ' - ' . $this->items->first()->order_number;
        }

        return null;
    }
}

我找到了解决方案。

[options][queue] 数组中添加了这一行:

'name' => env('RABBITMQ_EXCHANGE_NAME', env('RABBITMQ_QUEUE'))

关于 rabbitmq 配置的文档,在 Laravel .env 中设置如下;

RABBITMQ_HOST=localhost
RABBITMQ_PORT=5672
RABBITMQ_VHOST=/
RABBITMQ_LOGIN=test
RABBITMQ_PASSWORD=test
RABBITMQ_QUEUE=reporting
RABBITMQ_JOB_QUEUE=dev
# Exchange name is a required field. 
RABBITMQ_EXCHANGE_NAME=yourexchangename

在您的 queue.php 文件中设置交换名称环境变量。

'worker' => [
    'driver' => 'rabbitmq',
    'factory_class' => Enqueue\AmqpLib\AmqpConnectionFactory::class,
    'host' => env('RABBITMQ_HOST'),
    'port' => env('RABBITMQ_PORT'),
    'vhost' => env('RABBITMQ_VHOST'),
    'login' => env('RABBITMQ_LOGIN'),
    'password' => env('RABBITMQ_PASSWORD'),
    'queue' => env('RABBITMQ_JOB_QUEUE'),

    'options' => [
        'exchange' => [
            // Exchange name is a required field. 
            'name' => env('RABBITMQ_EXCHANGE_NAME', null),
            /*
            * Determine if exchange should be created if it does not exist.
            */
            'declare' => env('RABBITMQ_EXCHANGE_DECLARE', true),
            /*
            * Read more about possible values at https://www.rabbitmq.com/tutorials/amqp-concepts.html
            */
            'type' => env('RABBITMQ_EXCHANGE_TYPE', \Interop\Amqp\AmqpTopic::TYPE_DIRECT),
            'passive' => env('RABBITMQ_EXCHANGE_PASSIVE', false),
            'durable' => env('RABBITMQ_EXCHANGE_DURABLE', true),
            'auto_delete' => env('RABBITMQ_EXCHANGE_AUTODELETE', false),
            'arguments' => env('RABBITMQ_EXCHANGE_ARGUMENTS'),
        ],
        'queue' => [
            'name' => env('RABBITMQ_EXCHANGE_NAME', env('RABBITMQ_QUEUE')),
            /*
            * Determine if queue should be created if it does not exist.
            */
            'declare' => env('RABBITMQ_QUEUE_DECLARE', true),
            /*
            * Determine if queue should be binded to the exchange created.
            */
            'bind' => env('RABBITMQ_QUEUE_DECLARE_BIND', true),
            /*
            * Read more about possible values at https://www.rabbitmq.com/tutorials/amqp-concepts.html
            */
            'passive' => env('RABBITMQ_QUEUE_PASSIVE', false),
            'durable' => env('RABBITMQ_QUEUE_DURABLE', true),
            'exclusive' => env('RABBITMQ_QUEUE_EXCLUSIVE', false),
            'auto_delete' => env('RABBITMQ_QUEUE_AUTODELETE', false),
            'arguments' => env('RABBITMQ_QUEUE_ARGUMENTS'),
        ],
    ],
],

为Laravel

定义rabbitmq驱动的另一个例子
'connections' => [
    // ...
    'rabbitmq' => [

        'driver' => 'rabbitmq',

        /*
         * Set to "horizon" if you wish to use Laravel Horizon.
         */
        'worker' => env('RABBITMQ_WORKER', 'default'),

        'dsn' => env('RABBITMQ_DSN', null),

        /*
         * Could be one a class that implements \Interop\Amqp\AmqpConnectionFactory for example:
         *  - \EnqueueAmqpExt\AmqpConnectionFactory if you install enqueue/amqp-ext
         *  - \EnqueueAmqpLib\AmqpConnectionFactory if you install enqueue/amqp-lib
         *  - \EnqueueAmqpBunny\AmqpConnectionFactory if you install enqueue/amqp-bunny
         */

        'factory_class' => Enqueue\AmqpLib\AmqpConnectionFactory::class,

        'host' => env('RABBITMQ_HOST', '127.0.0.1'),
        'port' => env('RABBITMQ_PORT', 5672),

        'vhost' => env('RABBITMQ_VHOST', '/'),
        'login' => env('RABBITMQ_LOGIN', 'guest'),
        'password' => env('RABBITMQ_PASSWORD', 'guest'),

        'queue' => env('RABBITMQ_QUEUE', 'default'),

        'options' => [

            'exchange' => [

                'name' => env('RABBITMQ_EXCHANGE_NAME'),

                /*
                 * Determine if exchange should be created if it does not exist.
                 */

                'declare' => env('RABBITMQ_EXCHANGE_DECLARE', true),

                /*
                 * Read more about possible values at https://www.rabbitmq.com/tutorials/amqp-concepts.html
                 */

                'type' => env('RABBITMQ_EXCHANGE_TYPE', \Interop\Amqp\AmqpTopic::TYPE_DIRECT),
                'passive' => env('RABBITMQ_EXCHANGE_PASSIVE', false),
                'durable' => env('RABBITMQ_EXCHANGE_DURABLE', true),
                'auto_delete' => env('RABBITMQ_EXCHANGE_AUTODELETE', false),
                'arguments' => env('RABBITMQ_EXCHANGE_ARGUMENTS'),
            ],

            'queue' => [

                /*
                 * Determine if queue should be created if it does not exist.
                 */

                'declare' => env('RABBITMQ_QUEUE_DECLARE', true),

                /*
                 * Determine if queue should be binded to the exchange created.
                 */

                'bind' => env('RABBITMQ_QUEUE_DECLARE_BIND', true),

                /*
                 * Read more about possible values at https://www.rabbitmq.com/tutorials/amqp-concepts.html
                 */

                'passive' => env('RABBITMQ_QUEUE_PASSIVE', false),
                'durable' => env('RABBITMQ_QUEUE_DURABLE', true),
                'exclusive' => env('RABBITMQ_QUEUE_EXCLUSIVE', false),
                'auto_delete' => env('RABBITMQ_QUEUE_AUTODELETE', false),
                'arguments' => env('RABBITMQ_QUEUE_ARGUMENTS'),
            ],
        ],

        /*
         * Determine the number of seconds to sleep if there's an error communicating with rabbitmq
         * If set to false, it'll throw an exception rather than doing the sleep for X seconds.
         */

        'sleep_on_error' => env('RABBITMQ_ERROR_SLEEP', 5),

        /*
         * Optional SSL params if an SSL connection is used
         * Using an SSL connection will also require to configure your RabbitMQ to enable SSL. More details can be founds here: https://www.rabbitmq.com/ssl.html
         */

        'ssl_params' => [
            'ssl_on' => env('RABBITMQ_SSL', false),
            'cafile' => env('RABBITMQ_SSL_CAFILE', null),
            'local_cert' => env('RABBITMQ_SSL_LOCALCERT', null),
            'local_key' => env('RABBITMQ_SSL_LOCALKEY', null),
            'verify_peer' => env('RABBITMQ_SSL_VERIFY_PEER', true),
            'passphrase' => env('RABBITMQ_SSL_PASSPHRASE', null),
        ],   

    ],
    // ...    
],