Fastadmin 使用RabbitMQ队列

在Fastadmin 简单使用RabbitMQ队列实现消息的收发

目录

在php中进行消息的收发

安装依赖库

安装php-amqplib

安装ext-sockets扩展

手动开启

小皮面板

重新安装依赖库

[配置 RabbitMQ 连接信息](#配置 RabbitMQ 连接信息)

[封装 RabbitMQ 基础类](#封装 RabbitMQ 基础类)

实现生产者(发送消息)

实现消费者(处理消息)

[步骤 1:创建消费者命令](#步骤 1:创建消费者命令)

[步骤 2:注册命令](#步骤 2:注册命令)

[步骤 3:启动消费者](#步骤 3:启动消费者)

测试验证

注意事项

总结


在php中进行消息的收发

在 PHP 中操作 RabbitMQ 需要借助php-amqplib扩展,以下是通过 PHP 代码实现消息收发(生产者和消费者)的详细步骤:

安装依赖库

安装php-amqplib

使用 Composer 安装php-amqplib(RabbitMQ 的 PHP 客户端库):

bash 复制代码
composer require php-amqplib/php-amqplib

问题:最高只能安装到2.8版本,使用的rabbitmq链接代码较为落后。

安装提示:Cannot use php-amqplib/php-amqplib's latest version v3.7.3 as it requires ext-sockets * which is missing from your platform.

解决问题:

这个错误提示说明:php-amqplib v3.7.3 依赖 PHP 的 ext-sockets 扩展,但你的 PHP 环境中没有启用该扩展,导致安装失败。

安装ext-sockets扩展
手动开启

Windows 下的 PHP 通常已预编译 sockets 扩展,只需手动启用:

找到 PHP 的配置文件 php.ini:

打开 php.ini,搜索 extension=sockets:

若找到该行且前面有 ;(注释),去掉 ; 即可(如 ;extension=sockets → extension=sockets)。

若未找到,直接添加一行:extension=sockets(注意:PHP 7.0+ 通常不需要加 php_ 前缀,旧版本可能是 extension=php_sockets.dll)。

保存文件,重启 Web 服务器(如 Apache、Nginx)或 PHP 进程。

小皮面板

在网站列表,找到相应网站,选择php扩展,找到sockets打开,然后重启服务即可。

扩展如下:

重新安装依赖库

先卸载安装的2.8版本 php-amqplib/php-amqplib

bash 复制代码
composer remove php-amqplib/php-amqplib

这次安装的版本为3.7,如下:

配置 RabbitMQ 连接信息

在application/config.php文件下新增rabbitmq配置文件,存放连接参数:

php 复制代码
// +----------------------------------------------------------------------
// | Rabbit设置
// +----------------------------------------------------------------------
'rabbit'                   => [
    // RabbitMQ主机
    'host'      => '127.0.0.1',
    // 端口
    'port'      => 5672,
    // 用户名(默认guest,仅本地访问)
    'user'      => 'guest',
    // 密码
    'password'  => 'guest',
    // 虚拟主机
    'vhost'     => '/',
    // 心跳检测时间(秒)
    'heartbeat' => 60,
    // 默认队列名称
    'queue'     => [
        'default' => 'fastadmin_default_queue',
    ]
],

封装 RabbitMQ 基础类

创建基础工具类处理连接、通道和队列声明,减少重复代码。

在application/common/library目录下新建RabbitMQ.php:

php 复制代码
<?php
namespace app\common\library;

use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use think\Config;

class RabbitMQ
{
    protected $connection;  // 连接对象

    protected $channel;     // 通道对象

    protected $config;      // 配置参数

    public function __construct()
    {
        $this->config = Config::get('rabbitmq');
        $this->connect();
    }

    // 建立连接
    protected function connect()
    {
        try {
            $this->connection = new AMQPStreamConnection(
                $this->config['host'],
                $this->config['port'],
                $this->config['user'],
                $this->config['password'],
                $this->config['vhost'],
                false,
                'AMQPLAIN',
                null,
                'en_US',
                $this->config['heartbeat'],
                null
            );
            $this->channel = $this->connection->channel();
        } catch (\Exception $e) {
            throw new \Exception("RabbitMQ连接失败:" . $e->getMessage());
        }
    }

    // 声明队列(确保队列存在)
    public function declareQueue($queueName = null)
    {
        $queue = $queueName ?: $this->config['queue']['default'];
        // 参数:队列名、是否持久化、是否排他、是否自动删除、其他参数
        $this->channel->queue_declare($queue, false, true, false, false);
        return $queue;
    }

    // 发送消息到队列
    public function send($data, $queueName = null)
    {
        $queue = $this->declareQueue($queueName);
        $message = new AMQPMessage(
            json_encode($data, JSON_UNESCAPED_UNICODE),
            ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]  // 消息持久化
        );
        $this->channel->basic_publish($message, '', $queue);
    }

    // 消费消息(回调处理)
    public function consume($callback, $queueName = null)
    {
        $queue = $this->declareQueue($queueName);
        // 参数:队列名、消费者标签、是否自动确认、是否排他、是否本地、是否阻塞、回调函数
        $this->channel->basic_consume($queue, '', false, false, false, false, $callback);

        // 循环监听消息
        while ($this->channel->is_consuming()) {
            $this->channel->wait();
        }
    }

    // 关闭连接
    public function close()
    {
        if ($this->channel) {
            $this->channel->close();
        }
        if ($this->connection) {
            $this->connection->close();
        }
    }

    // 析构函数自动关闭连接
    public function __destruct()
    {
        $this->close();
    }
}

实现生产者(发送消息)

在业务逻辑中调用RabbitMQ类发送消息到队列(例如控制器中):

在api/Demo.php中新增sendMessage方法,如下:

php 复制代码
// 示例:发送消息到队列
public function sendMessage()
{
    try {
        $rabbitMQ = new RabbitMQ();
        // 发送的数据(数组格式)
        $data = [
            'id' => 123,
            'content' => '这是一条测试消息',
            'time' => date('Y-m-d H:i:s')
        ];
        // 发送到默认队列(也可指定队列名:$rabbitMQ->send($data, 'custom_queue'))
        $rabbitMQ->send($data);
        return '消息发送成功';
    } catch (\Exception $e) {
        return '发送失败:' . $e->getMessage();
    }
}

实现消费者(处理消息)

消费者需持续运行监听队列,建议通过命令行脚本实现(FastAdmin 基于 ThinkPHP 的命令行机制)。

步骤 1:创建消费者命令

在application/common/command目录下新建RabbitMQConsumer.php:

php 复制代码
<?php
namespace app\common\command;

use app\common\library\RabbitMQ;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Log;

class RabbitMQConsumer extends Command
{
    // 配置命令
    protected function configure()
    {
        $this->setName('rabbitmq:consumer')  // 命令名:php think rabbitmq:consumer
        ->setDescription('RabbitMQ消费者,处理队列消息');
    }

    // 执行命令
    protected function execute(Input $input, Output $output)
    {
        $output->writeln('消费者启动成功,开始监听队列...');
        try {
            $rabbitMQ = new RabbitMQ();
            // 消息处理回调函数
            $callback = function ($msg) use ($output) {
                $output->writeln('收到消息:' . $msg->body);
                // 解析消息(原发送的数组)
                $data = json_decode($msg->body, true);
                if (empty($data)) {
                    $output->writeln('消息格式错误');
                    $msg->nack(false, false);  // 拒绝消息,不重新入队
                    return;
                }

                // 业务处理逻辑(例如:发送邮件、生成报表等)
                try {
                    // TODO: 这里写具体的处理代码
                    $output->writeln('处理成功:' . $data['id']);
                    $msg->ack();  // 确认消息已处理(从队列删除)
                } catch (\Exception $e) {
                    Log::error('消息处理失败:' . $e->getMessage());
                    $msg->nack(false, true);  // 处理失败,重新入队(可限制重试次数)
                }
            };

            // 监听默认队列(可指定队列名:$rabbitMQ->consume($callback, 'custom_queue'))
            $rabbitMQ->consume($callback);
        } catch (\Exception $e) {
            $output->writeln('消费者异常:' . $e->getMessage());
            Log::error('消费者异常:' . $e->getMessage());
        }
    }
}
步骤 2:注册命令

在application/command.php中注册命令:

php 复制代码
return [
    'app\admin\command\Crud',
    'app\admin\command\Menu',
    'app\admin\command\Install',
    'app\admin\command\Min',
    'app\admin\command\Addon',
    'app\admin\command\Api',
    'app\common\command\RabbitMQConsumer', # 消费者
];
步骤 3:启动消费者

在项目根目录执行命令启动消费者:

bash 复制代码
php think rabbitmq:consumer

若需在后台运行(生产环境),可结合supervisor管理进程(确保进程意外退出后自动重启)。

效果如下:

测试验证

访问http://你的域名/api/demo/sendMessage发送测试消息。

查看消费者控制台输出,应显示 "收到消息" 和处理结果。

请求效果:

处理效果:

若处理失败,消息会重新入队(根据nack参数配置)。

注意事项

消息持久化:队列和消息均需设置持久化(已在基础类中配置),避免 RabbitMQ 重启后消息丢失。

错误处理:消费者需捕获业务异常,通过ack()/nack()控制消息状态,避免死循环。

性能优化:生产环境可根据需求调整消费者数量(多个进程同时消费),或使用交换机(Exchange)分发消息到不同队列。

权限问题:默认guest用户仅允许本地访问,远程连接需创建新用户并授权(通过 RabbitMQ 管理界面:http://ip:15672)。

总结

在Fastadmin 简单使用RabbitMQ队列实现消息的收发

相关推荐
Gerardisite4 小时前
如何在微信个人号开发中有效管理API接口?
java·开发语言·python·微信·php
2501_941225686 小时前
Go语言高性能API网关设计与gRPC实战分享:微服务接口优化与负载均衡经验
rabbitmq
源码梦想家7 小时前
面向未来软件工程实践:基于Go语言的高并发架构设计思考与经验分享案例分析研究方法探讨
rabbitmq
2501_941147717 小时前
高并发CDN与边缘计算在互联网系统优化实践经验分享
rabbitmq
2501_941143739 小时前
分布式日志系统与可观测性在高并发互联网系统架构优化与实践分享
rabbitmq
debug骑士9 小时前
面向安全与高性能微服务的Rust异步架构设计与工程化实践经验分享探索研究
rabbitmq
2501_9418017610 小时前
人工智能与物联网:智能家居生态的崛起与未来
rabbitmq
2501_9411433210 小时前
基于 Node.js 构建高并发实时 Web 应用与微服务系统的架构设计实践分享
rabbitmq
源码梦想家11 小时前
数字孪生应用深化背景下在珠海基于 Rust 构建城市级实时三维仿真平台的体系架构与工程实践研究
rabbitmq