eduzz/hermes

此库负责封装与队列管理器的连接。主要针对与 RabbitMQ 的使用。


README

此库负责封装与队列管理器的连接。主要针对与 RabbitMQ 的使用。

** 依赖:PHP 5.3 ** 由于使用了命名空间。

** 依赖:bcmath 和 mbstring ** 由于使用了 php-amqplib 通过 AMQP 0-9-1 协议进行连接。

安装

首先,将 Hermes 的依赖和仓库添加到我们的 composer.json 文件中

{
    "require": {
        "eduzz/hermes": "dev-master"
    },
    "repositories": [
        {
            "type": "vcs",
            "url":  "git@github.com:eduzz/hermes.git"
        }
    ]
}

然后,运行以下命令

composer dump-autoload

以更新 composer 缓存

composer install

以安装依赖和 Hermes

PS:在安装 Hermes 的 shell 中,需要确保你有连接到 GitHub 的密钥。

在 Laravel 项目中安装

下一步是将 Hermes 注册到 service providers 列表中,在 config/app.php 中,将 Hermes 添加到 providers 列表中,并将 Hermes facade 添加到 aliases 列表中。

'providers' => [
    // ...

    Eduzz\Hermes\HermesLaravelServiceProvider::class,
],
'aliases' => [
    // ...

    'Hermes' => Eduzz\Hermes\Facades\HermesFacade::class,
],

我们需要清除缓存,更新我们的包,并发布 Hermes 的配置

php artisan cache:config
composer update
php artisan vendor:publish --tag="config"

如果一切顺利,将显示以下消息

Copied File [/vendor/eduzz/src/Config/hermes.php] To [/config/hermes.php]

因此,需要在 config/hermes.php 文件中的 connection 变量中配置 Hermes,这是您的连接数据所在之处,例如

<?php

return [
    'connection' =>  [
        'host' => env('HERMES_HOST', '127.0.0.1'),
        'port' => env('HERMES_PORT', 5672),
        'username' => env('HERMES_USERNAME', 'guest'),
        'password' => env('HERMES_PASSWORD', 'guest'),
        'vhost' => env('HERMES_VHOST', '/'),
        'connection_name' => env('HERMES_CONNECTION_NAME', '/'),
    ]
];

在 Lumen 项目中安装

对于 Lumen 项目的安装,需要手动创建配置文件,在 config 文件夹中添加一个名为 hermes.php 的文件,内容如下

<?php

return [
    'connection' =>  [
        'host' => env('HERMES_HOST', '127.0.0.1'),
        'port' => env('HERMES_PORT', 5672),
        'username' => env('HERMES_USERNAME', 'guest'),
        'password' => env('HERMES_PASSWORD', 'guest'),
        'vhost' => env('HERMES_VHOST', '/'),
        'connection_name' => env('HERMES_CONNECTION_NAME', '/'),
    ]
];

然后,在 bootstrap/app.php 文件中注册我们的 service provider,找到注册行并添加

<?php
// ...
$app->register(Eduzz\Hermes\HermesLaravelServiceProvider::class);
// ...

在 bootstrap/app.php 中添加对 Hermes 配置的调用

<?php
$app->configure('hermes');

return $app;

在没有 Illuminate 框架的项目中安装

在没有 Laravel/Lumen 的项目中使用 Hermes,需要手动设置配置,例如

<?php

require 'vendor/autoload.php';

use Eduzz\Hermes\Hermes;

$hermes = new Hermes([
	'host'  =>  '127.0.0.1',
	'port' => 5672,
	'username' => 'guest',
	'password' => 'guest',
	'vhost' => '/'
]);

有一个名为 setConfig 的方法,可以在不通过构造函数的情况下更新配置。

使用方法

Hermes 与 rabbitMQ 有两种交互,声明队列,消费队列和发送消息。

发送消息

定义消息

为了定义一个新消息,需要扩展我们的抽象消息

<?php

namespace App\HermesMessages;

use Eduzz\Hermes\Message\AbstractMessage;

class ExampleMessage extends AbstractMessage
{
    public function __construct($id, $message)
    {
        parent::__construct(
            // Sua routing Key
            'app.module.action',

            // Seu payload
            ['id' => $id, 'message' => $message]
        );
    }
}

在您的消息中,无论逻辑如何,都可以传递任何数据,但是 Hermes 消息必须始终接收一个字符串作为 routingKey,第二个参数是任意数据的数组。

在 Laravel/Lumen 中发送消息

我们将使用 Laravel 的依赖注入来实例化 Hermes,并获取 config/hermes.php 文件中的配置,以下是一个使用 Hermes 的 Laravel 控制器示例

<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller as BaseController;
use Eduzz\Hermes\Hermes;

use App\HermesMessages\ExampleMessage;

class Controller extends BaseController
{
    private $hermes;

    public function __construct(Hermes $hermes) {
        $this->hermes = $hermes;

        parent::__construct();
    }

    public function method() {
        // Sua lógica aqui

        $this->hermes->publish(
            new ExampleMessage(5, 'Hello world'),
            'my_exchange' // Paramêtro opcional, qual exchange a mensagem deve ir
        );
    }
}

publish 方法中的第二个参数(exchange)是可选的,它是消息将发送到的 exchange,默认使用名为 'eduzz' 的 exchange。

在没有框架的情况下使用 Hermes 发送消息

逻辑相同,但是通过构造函数或 setConfig 传递配置,例如:return array( 'connection' => array( 'host' => env('HERMES_HOST', '127.0.0.1'), 'port' => env('HERMES_PORT', 5672), 'username' => env('HERMES_USERNAME', 'guest'), 'password' => env('HERMES_PASSWORD', 'guest'), 'vhost' => env('HERMES_VHOST', '/'). 'connection_name' => env('HERMES_CONNECTION_NAME', '/'), ) );

<?php

$hermes->publish(
    new Message(
        [
            "id" => 123,
            "name" => "John Doe",
            "age" => 18
        ],
        'my_exchange' // Paramêtro opcional, qual exchange a mensagem deve ir
    );
);

声明和消费队列

添加新的队列

要使用我们交易所(topic)的工作模式消费队列,需要声明一个队列并执行一个'bind'操作。bind操作是将一个队列绑定到一个routingKey上,也就是说,具有某个特定routingKey的消息将会被发送到我们创建的队列中。

Esquema de topic em filas

我们将使用Hermes来声明一个队列并进行bind操作。

<?php

$queueName = $hermes->addQueue(
        'queue_name', // Se for uma string vazia, irá criar um nome aleatório
        true, // Ativa o nack e cria uma fila adicional chamada queue_name.nack, o paramêtro é opcional e o default é a fila ativa
        true // Parâmetro opcional de fila durável ou não, o padrão é durável
    )
        ->bind(
            'my.routing.key',
            null, // Parâmetro opcional de nome da fila, se for null, irá pegar o nome da última fila criada
            'custom_exchange'; // Parâmetro opcional exchange, se não for passado, irá pegar a exchange default 'eduzz'
        )
        ->getLastQueueCreated(); // Retorna o nome da última fila criada

消费队列

为了消费队列,我们需要为我们创建的队列添加一个回调函数,然后调用Hermes的start方法来启动队列的处理。

<?php

$hermes->addListenerTo(
    'queue_name',
    function($msg) {
        echo json_encode($msg->body);
    },
    true // Ativa ou não a opção de errorHandling do Hermes
);

$hermes->start();

如果Hermes的errorHandling功能已启用,则连接的队列必须启用nack功能。未捕获的异常将在回调函数中处理,并将消息内容发送到nack队列。

如果nack已启用且errorHandling未启用,则在其回调函数中,需要使用ack和nack方法,例如:

<?php

$hermes->addListenerTo(
	'queue_name',
	function($msg) use ($hermes) {
		try {
			echo json_encode($msg->body);

			return $hermes->consumer()->ack($msg);
		 catch(\Exception $e) {
			return $hermes->consumer()->nack($msg);
		}
	},
	false // Error handling desativado
);

$hermes->start();