itprojektrepo/laravel-aws-pubsub

一个Laravel广播驱动和队列驱动,利用AWS SNS、EventBridge和SQS广播并监听发布的事件。

0.5.5 2024-06-13 08:40 UTC

This package is not auto-updated.

Last update: 2024-09-20 08:00:37 UTC


README

Latest Version on Packagist GitHub Workflow Status Software License Total Downloads

酒吧

类似于Pusher,此包提供Laravel Broadcasting驱动,用于AWS SNS(简单通知服务)和AWS EventBridge以发布服务器端事件。

我们理解Broadcasting通常用于“广播”您的服务器端Laravel Events通过WebSocket连接到您的客户端JavaScript应用程序。然而,我们认为这种利用广播的方法对于Pub/Sub架构很有意义,其中应用程序希望将服务器端事件广播到外部世界,关于刚刚发生的事情。

在这种情况下,“频道”可以与使用SNS驱动时的“主题”以及使用EventBridge驱动时的“事件总线”相类比。

订阅

这部分相当直接,我们只需监听推送到SQS队列的消息并对它们采取行动即可。这里唯一的区别是我们不使用默认的Laravel SQS驱动,因为推送的消息不遵循从Laravel应用程序推送的Laravel经典JSON有效负载的队列作业/事件。SNS的消息更简单。

先决条件

  1. 此包在两个Laravel应用程序(发布者和订阅者)上安装和配置
  2. 至少一个SQS队列 - 每个订阅的Laravel应用程序一个队列
  3. 至少一个SNS主题
  4. 在SNS主题和SQS队列之间有一个SQS订阅,带有“原始消息投递”禁用
  5. 配置相关的访问策略,特别是如果您想直接从AWS控制台发布消息的话。

安装

您可以通过Composer在Laravel 8+应用程序上安装此包

composer require pod-point/laravel-aws-pubsub

注意:对于Laravel 5.x、6.x或7.x,您可以使用pod-point/laravel-aws-pubsub:^0.0.1

此包需要一个单独的服务提供器,请通过运行以下命令安装它

php artisan pubsub:install

这将创建App\Providers\PubSubEventServiceProvider并在您的config/app.php文件中自动加载它。

发布/广播

配置

您需要在config/broadcasting.php配置文件中添加以下连接并配置您的SNS凭据

'connections' => [
    // ...
    'sns' => [
        'driver' => 'sns',
        'region' => env('AWS_DEFAULT_REGION'),
        'key' => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
        'arn-prefix' => env('BROADCAST_TOPIC_ARN_PREFIX'),
        'arn-suffix' => env('BROADCAST_TOPIC_ARN_SUFFIX'),
    ],

    'eventbridge' => [
        'driver' => 'eventbridge',
        'region' => env('AWS_DEFAULT_REGION'),
        'key' => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
        'source' => env('AWS_EVENTBRIDGE_SOURCE'),
    ],
    // ...
],

确保根据需要定义您的环境变量

# both drivers require:
AWS_DEFAULT_REGION=you-region
AWS_ACCESS_KEY_ID=your-aws-key
AWS_SECRET_ACCESS_KEY=your-aws-secret

# SNS driver only:
BROADCAST_TOPIC_ARN_PREFIX=arn:aws:sns:us-east-1:123456789: # up until your Topic name
BROADCAST_TOPIC_ARN_SUFFIX=-local # optional

# EventBridge driver only:
AWS_EVENTBRIDGE_SOURCE=com.your-app-name

可以使用arn-suffix帮助管理不同环境下的SNS主题。它将在构建完整的SNS主题ARN时添加到末尾。

接下来,您需要确保在.env文件中使用sns广播驱动作为默认驱动进行广播

BROADCAST_DRIVER=sns

BROADCAST_DRIVER=eventbridge

请记住,如果您需要能够同时使用两个驱动程序,则可以在事件级别定义连接。

用法

只需按照官方文档中解释的默认方式广播 Laravel 事件(官方文档)

以类似的方式,您需要确保实现Illuminate\Contracts\Broadcasting\ShouldBroadcast接口,并定义您希望广播的频道/主题。

use App\Models\Order;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;

class OrderShipped implements ShouldBroadcast
{
    use SerializesModels;

    /**
     * The order that was shipped.
     *
     * @var \App\Models\Order
     */
    public $order;

    /**
     * Create a new event instance.
     *
     * @param  \App\Models\Order  $order
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * Get the topics that model events should broadcast on.
     *
     * @return array
     */
    public function broadcastOn()
    {
        return ['orders']; // This is the Topic name for the ARN 'arn:aws:sns:us-east-1:123456789:orders' for example
    }
}

广播数据

默认情况下,该包将发布默认的 Laravel 负载数据,这已在广播事件时使用。一旦发布,其 JSON 表示形式可能如下所示

{
    "order": {
        "id": 1,
        "name": "Some Goods",
        "total": 123456,
        "created_at": "2021-06-29T13:21:36.000000Z",
        "updated_at": "2021-06-29T13:21:36.000000Z"
    },
    "connection": null,
    "queue": null
}

默认情况下,Laravel 将自动将任何其他公开属性添加到负载数据中

use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;

class OrderShipped implements ShouldBroadcast
{
    use SerializesModels;

    public $action = 'parcel_handled';

    // ...
}

这将产生以下负载数据

{
    "action": "parcel_handled",
    "order": {
        "id": 1,
        "name": "Some Goods",
        "total": 123456,
        "created_at": "2021-06-29T13:21:36.000000Z",
        "updated_at": "2021-06-29T13:21:36.000000Z"
    },
    "connection": null,
    "queue": null
}

但是,通过使用 broadcastWith 方法,您将能够定义要发布的确切类型的负载数据。

/**
 * Get and format the data to broadcast.
 *
 * @return array
 */
public function broadcastWith()
{
    return [
        'action' => 'parcel_handled',
        'data' => [
            'order-id' => $this->order->id,
            'order-total' => $this->order->total,
        ],
    ];
}

现在,当事件被触发时,它将表现得像一个标准的 Laravel 事件,这意味着其他监听器可以像往常一样监听它,但它也将通过使用 broadcastOn 方法定义的主题和 broadcastWith 方法定义的负载数据进行广播。

广播名称/主题

在发布/订阅上下文中,为广播到 SNS 的每个通知指定一个 Subject 可能很有用。这可以是一种配置特定主题监听器的简单方法,您可以接收并稍后处理队列中的这些主题。

默认情况下,该包将使用标准的 Laravel 广播名称 来定义发送通知的 Subject。您可以根据需要自由地对其进行自定义。

/**
 * The event's broadcast name/subject.
 *
 * @return string
 */
public function broadcastAs()
{
    return "orders.{$this->action}";
}

模型广播

如果您熟悉 模型广播,您已经知道 Eloquent 模型在其生命周期中会派发多个事件并相应地广播它们。

在模型广播的上下文中,以下模型事件可以被广播

  • created
  • updated
  • deleted
  • trashed 如果启用了软删除
  • restored 如果启用了软删除

为了广播模型事件,您需要在您的模型上使用 Illuminate\Database\Eloquent\BroadcastsEvents 特性并遵循官方文档。

您可以在模型上使用 broadcastOnbroadcastWithbroadcastAs 方法来自定义主题名称、负载数据和主题。

注意:模型广播仅在 Laravel 8.x 中可用。如果您希望使用旧版本的 Laravel 执行类似操作,我们建议您从 模型观察器 函数手动派发一些“可广播”的事件。

订阅/监听

配置

一旦安装了该包,并且类似于您为标准 Laravel SQS 队列所做的那样,您需要在 config/queue.php 配置文件中添加以下连接并配置您的凭证

'connections' => [
    // ...
    'sqs-sns' => [
        'driver' => 'sqs-sns',
        'key' => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
        'prefix' => env('SQS_SNS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
        'queue' => env('SQS_SNS_QUEUE', 'pub-sub'),
        'suffix' => env('SQS_SNS_SUFFIX'),
        'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    ],
    // ...
],

一旦正确配置了队列,您将需要能够定义您希望为哪种传入事件使用哪种监听器。为此,您需要创建 Laravel 监听器并通过包为您创建的服务提供商将它们关联起来。

注册事件和监听器

您需要一个单独的服务提供商来定义每个发布/订阅事件及其监听器的映射。我们提供了 App\Providers\PubSubEventServiceProvider,您应该在安装包时通过运行 php artisan pubsub:install 已经安装了它。

listen 属性包含所有事件(键)及其监听器(值)的数组。与标准的 Laravel EventServiceProvider 不同,您可以为每个事件定义一个监听器,但您可以根据应用程序的需要向此数组添加尽可能多的事件。

使用 SNS 消息的广播名称/主题

您可以使用其 广播名称/主题 来定义 Pub/Sub 事件。例如,让我们添加一个以 orders.shipped 作为其 Subject(即广播名称)的事件。

use App\Listeners\PubSub\SendShipmentNotification;

/**
 * The event handler mappings for subscribing to PubSub events.
 *
 * @var array
 */
protected $listen = [
    'orders.shipped' => [
        SendShipmentNotification::class,
    ],
];

使用 SNS 主题名称

作为一个后备方案,您还可以使用 SNS 主题本身的 ARN,并为来自该主题的任何事件(尚未映射到现有的基于主题的事件/监听器对)创建一个更通用的监听器。

例如,让我们为任何推送到给定 SNS 主题的事件添加一个通用的后备监听器。

use App\Listeners\PubSub\OrdersListener;

/**
 * The event handler mappings for subscribing to PubSub events.
 *
 * @var array
 */
protected $listen = [
    'orders.shipped' => [
        UpdateTrackingNumber::class,
        SendShipmentNotification::class,
    ],
    'arn:aws:sns:us-east-1:123456789:orders' => [
        OrdersListener::class,
    ],
];

您可以从这个通用的 OrdersListener 做任何您想做的事情,甚至可以在您的应用程序内部分发更多事件

注意:基于主题的事件/监听器对应该最后注册,以便基于主题的监听器优先。

定义监听器

在这里,我们只是重新使用了标准的 Laravel 事件监听器。唯一的区别是主 handle() 方法的定义略有不同。我们不是期望传入一个事件类的实例,而是简单地接收 payload 和(如果有的话)subject

/**
 * Handle the event.
 *
 * @return void
 */
public function handle(array $payload, string $subject = '')
{
    // ...
}

您可以像使用标准的 Laravel 监听器一样自由地排队这些监听器。

生成监听器

我们还提供了一个方便的命令来为您生成这些类。

artisan pubsub:make:listener SendShipmentNotification

注意:您仍然需要确保 PubSubEventServiceProvider 内部的映射已配置。

测试

使用以下命令运行测试

composer test

变更日志

请参阅我们的 发布记录 以获取有关最近更改的更多信息。

贡献

有关详细信息,请参阅 CONTRIBUTING

鸣谢

许可证

MIT 许可证(MIT)。有关更多信息,请参阅 许可证文件

旅行不应破坏地球 🌍

用 ❤️ 制作于 Pod Point