You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel集成RabbitMQ能否消费其他编程语言生产的消息?

跨语言基于RabbitMQ的生产消费核心只需要保证AMQP层配置对齐、消息序列化规则一致即可,laravel-queue-rabbitmq底层基于原生php-amqplib实现,完全兼容其他语言发送的标准AMQP消息,不需要做底层协议改造,按以下步骤配置即可跑通:

实现步骤

1. Laravel(消费者端)配置

首先确保已安装vyuldashev/laravel-queue-rabbitmq扩展包,之后修改config/queue.php,新增rabbitmq连接配置,核心参数提前固定,和生产者侧保持完全一致:

'connections' => [
    // 其他已有队列连接保留即可
    'rabbitmq' => [
        'driver' => 'rabbitmq',
        'hosts' => [
            [
                'host' => env('RABBITMQ_HOST', '127.0.0.1'),
                'port' => env('RABBITMQ_PORT', 5672),
                'user' => env('RABBITMQ_USER', 'guest'),
                'password' => env('RABBITMQ_PASSWORD', 'guest'),
                'vhost' => env('RABBITMQ_VHOST', '/'),
            ],
        ],
        'queue' => env('RABBITMQ_QUEUE', 'cross_lang_jobs'),
        'options' => [
            'queue' => [
                'job' => \App\Jobs\CrossLangConsumeJob::class,
                'exchange' => 'cross_lang_exchange',
                'exchange_type' => 'direct',
                'exchange_routing_key' => 'cross_lang_key',
                'bind_queues' => true,
                'durable' => true,
            ],
            'consumer' => [
                'prefetch_count' => 10,
            ]
        ],
    ],
],

修改.env文件,将队列默认驱动改为rabbitmq。

接下来创建统一的跨语言消息消费任务类app/Jobs/CrossLangConsumeJob.php,注意不要引入SerializesModels trait,避免触发PHP专属的Eloquent模型序列化逻辑:

<?php
namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

class CrossLangConsumeJob implements ShouldQueue
{
    use InteractsWithQueue, Queueable;

    public array $payload;

    public int $tries = 3;
    public int $timeout = 60;

    public function __construct(array $payload)
    {
        $this->payload = $payload;
    }

    public function handle()
    {
        // 此处编写业务逻辑,$this->payload 即为Node侧发送的JSON消息解析后的数组
        logger('收到Node侧消息', $this->payload);
    }
}

2. 消息格式适配

默认情况下laravel-queue-rabbitmq会尝试解析Laravel框架专属的消息结构(包含job类名、序列化后的PHP对象等字段),跨语言消息没有这些字段会直接抛解析错误,需要加一个事件监听,在任务处理前把原生消息转换成框架可识别的格式。

在app/Providers/EventServiceProvider.php中注册队列事件监听:

protected $listen = [
    \Illuminate\Queue\Events\JobProcessing::class => [
        \App\Listeners\AdaptCrossLangRabbitMQMessage::class,
    ],
];

生成监听类app/Listeners/AdaptCrossLangRabbitMQMessage.php,代码如下:

<?php
namespace App\Listeners;

use App\Jobs\CrossLangConsumeJob;
use Illuminate\Queue\Events\JobProcessing;
use Illuminate\Support\Str;

class AdaptCrossLangRabbitMQMessage
{
    public function handle(JobProcessing $event)
    {
        if ($event->connectionName !== 'rabbitmq') {
            return;
        }

        $rawBody = $event->job->getRawBody();
        $payload = json_decode($rawBody, true);
        // 检测到是跨语言的无框架标识消息,手动组装成Laravel队列可识别的payload结构
        if (!isset($payload['job'])) {
            $event->job->setPayload(json_encode([
                'uuid' => Str::uuid()->toString(),
                'displayName' => CrossLangConsumeJob::class,
                'job' => 'Illuminate\Queue\CallQueuedHandler@call',
                'data' => [
                    'commandName' => CrossLangConsumeJob::class,
                    'command' => serialize(new CrossLangConsumeJob($payload)),
                ],
                'maxTries' => 3,
                'timeout' => 60,
                'attempts' => $event->job->attempts(),
            ]));
        }
    }
}

3. Node.js(生产者端)配置

Node侧使用标准AMQP客户端发送消息即可,不需要适配任何Laravel专属规则,只需保证交换机、队列、路由键、持久化配置和Laravel侧完全一致,消息体传标准JSON字符串:

const amqp = require('amqplib');

async function sendToLaravelQueue() {
    const conn = await amqp.connect('amqp://guest:guest@127.0.0.1:5672/');
    const channel = await conn.createChannel();

    // 以下三个名称必须和Laravel侧配置完全一致
    const EXCHANGE_NAME = 'cross_lang_exchange';
    const QUEUE_NAME = 'cross_lang_jobs';
    const ROUTING_KEY = 'cross_lang_key';

    await channel.assertExchange(EXCHANGE_NAME, 'direct', { durable: true });
    await channel.assertQueue(QUEUE_NAME, { durable: true });
    await channel.bindQueue(QUEUE_NAME, EXCHANGE_NAME, ROUTING_KEY);

    // 消息内容可自定义,不需要加任何Laravel相关字段
    const messageContent = JSON.stringify({
        order_id: 10086,
        user_id: 2001,
        remark: 'Node端生产的跨语言测试消息'
    });

    channel.publish(EXCHANGE_NAME, ROUTING_KEY, Buffer.from(messageContent), {
        persistent: true,
        contentType: 'application/json'
    });

    console.log('消息发送完成');
    await channel.close();
    await conn.close();
}

sendToLaravelQueue();
避坑说明
  • 跨语言队列场景禁止在消费任务中使用SerializesModels trait,该trait生成的PHP专属序列化格式其他语言无法识别,会导致反序列化报错。
  • 交换机名称、交换机类型、队列名称、路由键、消息持久化配置必须两端完全对齐,否则会出现消息投递不到队列、消费者无法消费的问题。
  • 跨语言传递的消息体统一用JSON格式,不要用PHP专属的serialize()格式生产消息,其他语言没有对应的可靠解析实现。
  • 启动消费进程直接用常规命令即可:php artisan queue:work rabbitmq,不需要添加额外参数。

内容的提问来源于stack exchange,提问作者royhara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 21:39:30