laravel实现AMQP(rabbitmq)生产者以及消费者

5 篇文章 0 订阅
3 篇文章 0 订阅

基于php-amqplib/php-amqplib组件适配laravel框架的amqp封装库

支持便捷可配置的队列工作模式 官网详情

在此基础上可支持延迟消息、死信队列等机制。

环境要求:

PHP版本: ^7.3|^8.0

需要开启的扩展: socket

其他:

  1. 如果需要实现延迟任务需要安装对应版本的rabbitmq延迟插件,以rabbitmq3.9.0版本为例:
wget https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/3.9.0/rabbitmq_delayed_message_exchange-3.9.0.ez
cp rabbitmq_delayed_message_exchange-3.9.0.ez /opt/rabbitmq/plugins/
rabbitmq-plugins enable rabbitmq_delayed_message_exchange

用法:

第一步 安装组件:
composer require sai97/laravel-amqp
第二步 发布服务以及配置:
php artisan vendor:publish --provider="Sai97\LaravelAmqp\AmqpQueueProviders"

执行完后会分别在app/config目录下生成amqp.php(amqp连接配置等)、app/QueueJob/DefaultQueueJob.php(默认队列任务)

amqp.php

<?php

use App\QueueJob\DefaultQueueJob;

return [
    "connection" => [
        "default" => [
            "host" => env("AMQP_HOST", "127.0.0.1"),
            "port" => env("AMQP_PORT", 5672),
            "user" => env("AMQP_USER", "root"),
            "password" => env("AMQP_PASSWORD", "root")
        ]
    ],

    "event" => [
        "default" => DefaultQueueJob::class,
    ]
];

connection为amqp连接配置,可根据自身业务去调整,完全对应php-amqplib/php-amqplib相关配置项, event是队列实例标识,最好和connection用相同的key以便管理。

目前可支持相关接口项:
 //获取连接名称
    public function getConnectName(): string;

    //获取交换机名称
    public function getExchangeName(): string;

    //获取交换机类型
    public function getExchangeType(): string;

    //获取队列名称
    public function getQueueName(): string;

    //获取路由KEY
    public function getRoutingKey(): string;

    //获取ContentType
    public function getContentType(): string;

    //是否开启死信模式
    public function isDeadLetter(): bool;

    //获取死信交换机名称
    public function getDeadLetterExchangeName(): string;

    //获取死信路由KEY
    public function getDeadLetterRoutingKey(): string;

    //获取死信队列名称
    public function getDeadLetterQueueName(): string;

    //是否开启延迟任务
    public function isDelay(): bool;

    //获取延迟任务过期时长
    public function getDelayTTL(): int;

    //获取队列附加参数
    public function getQueueArgs(): array;

    //获取回调函数
    public function getCallback(): callable;

    //是否自动提交ACK
    public function isAutoAck(): bool;

当然你也可以自定义队列实例,只要继承Sai97\LaravelAmqp\Queue基类即可,具体功能配置参数参考Sai97\LaravelAmqp\QueueInterface。

代码示例:

生产者:
$message = "This is message...";
$amqpQueueServices = new AmqpQueueServices(QueueFactory::getInstance(DefaultQueueJob::class));
$amqpQueueServices->producer($message);
消费者:

利用laravel自带的Command去定义一个RabbitMQWorker自定义命令行,仅需要定义一次,后续只需要更改amqp.php配置文件添加不同的队列实例绑定关系即可,以下是RabbitMQWorker演示代码:

<?php

namespace App\Console\Commands;


use Illuminate\Console\Command;
use Sai97\LaravelAmqp\AmqpQueueServices;
use Sai97\LaravelAmqp\QueueFactory;

class RabbitMQWorker extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'rabbitmq:worker {event}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'rabbitmq worker 消费进程';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        try {

            $event = $this->argument("event");

            $eventConfig = config("amqp.event");
            if (!isset($eventConfig[$event]) || empty($entity = $eventConfig[$event])) {
                return $this->error("未知的事件: {$event}");
            }
            
            $this->info("rabbitmq worker of event[{$event}] process start ...");

            $amqpQueueServices = new AmqpQueueServices(QueueFactory::getInstance($entity));
            $amqpQueueServices->consumer();

        } catch (\Throwable $throwable) {
            $event = $event ?? "";
            $this->error($throwable->getFile() . " [{$throwable->getLine()}]");
            return $this->error("rabbitmq worker of event[{$event}] process error:{$throwable->getMessage()}");
        }

        $this->info("rabbitmq worker of event[{$event}] process stop ...");
    }
}

完成RabbitMQWorker消费者命令后,我们只需执行php artisan rabbitmq:worker default 完成监听,其中default是可变的,请根据的amqp.php配置中的队列实例绑定标识去输入。

因为队列的消费者都需要是守护进程,所以我们可以依托supervisord进程管理器去定义RabbitMQWorker消费者命令,这样可以保证进程可后台允许以及重启启动等,以下是supervisord.conf配置文件示例:

[program:rabbitmq-worker-default]
#process_name=%(program_name)s_%(process_num)d
process_name=worker_%(process_num)d
numprocs=3
command=/usr/local/bin/php /app/www/laravel8/artisan rabbitmq:worker default
autostart=true
autorestart=true
startretries=3
priority=3
stdout_logfile=/var/log/rabbitmq-worker-default.log
redirect_stderr=true

搭配supervisord来进行管理消费者进程有许多便捷的方面:

  1. 如果需要新增一个队列实例,只需要按照上述格式复制一个program,可以在不影响其他进程的情况下进程更新supervisord配置:
supervisorctl update

    2. 通过配置numprocs参数来设定需要开启多少个相同配置项的消费者worker,这在任务分发、并行处理等场景十分适用,大大提高消费者执行效率。

这里不详细叙述supervisord相关操作,具体可查看supervisord官方文档

参考链接:https://github.com/Z-Sai/laravel-amqp

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,可以使用RabbitMQ的Java客户端库来实现RabbitMQ生产者。使用注解可以更方便地配置和管理RabbitMQ生产者。 以下是使用注解实现RabbitMQ生产者的步骤: 1. 添加RabbitMQ客户端库的依赖 ```xml <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.12.0</version> </dependency> ``` 2. 在Spring Boot应用程序的主类上添加@EnableRabbit注解 ```java @SpringBootApplication @EnableRabbit public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } } ``` 3. 定义RabbitMQ连接工厂和RabbitMQ模板 ```java @Configuration public class RabbitMQConfig { @Value("${spring.rabbitmq.host}") private String host; @Value("${spring.rabbitmq.port}") private int port; @Value("${spring.rabbitmq.username}") private String username; @Value("${spring.rabbitmq.password}") private String password; @Value("${spring.rabbitmq.virtual-host}") private String virtualHost; @Bean public ConnectionFactory connectionFactory() { CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setHost(host); connectionFactory.setPort(port); connectionFactory.setUsername(username); connectionFactory.setPassword(password); connectionFactory.setVirtualHost(virtualHost); return connectionFactory; } @Bean public RabbitTemplate rabbitTemplate() { return new RabbitTemplate(connectionFactory()); } } ``` 4. 定义RabbitMQ生产者 ```java @Component public class RabbitMQProducer { private static final String QUEUE_NAME = "my_queue"; @Autowired private RabbitTemplate rabbitTemplate; @Bean public Queue queue() { return new Queue(QUEUE_NAME); } @RabbitListener(queues = QUEUE_NAME) public void receiveMessage(String message) { System.out.println("Received message: " + message); } public void sendMessage(String message) { rabbitTemplate.convertAndSend(QUEUE_NAME, message); System.out.println("Sent message: " + message); } } ``` 在上面的代码中,我们定义了一个名为"my_queue"的队列,并使用@RabbitListener注解来监听该队列。在sendMessage方法中,我们使用RabbitTemplate将消息发送到队列中。 现在,我们可以在其他组件中注入RabbitMQProducer并调用它的sendMessage方法来发送消息到队列中。例如: ```java @RestController public class MyController { @Autowired private RabbitMQProducer rabbitMQProducer; @GetMapping("/sendMessage") public void sendMessage() { rabbitMQProducer.sendMessage("Hello, RabbitMQ!"); } } ``` 这样,当我们访问"/sendMessage"接口时,就会向"my_queue"队列发送一条消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值