foodticket/laravel-aws-pubsub

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

0.5.3 2024-08-26 08:39 UTC

This package is auto-updated.

Last update: 2024-09-26 09:04:50 UTC


README

Latest Version on Packagist GitHub Workflow Status Software License Total Downloads

酒吧

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

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

在这种情况下,当使用SNS驱动程序时,“通道”可以理解为“主题”,而当使用EventBridge驱动程序时,“事件总线”可以理解为“通道”。

订阅

这部分相当直接,我们只需要监听推送到SQS队列的消息并对其采取行动。这里唯一的区别是我们不使用默认的Laravel SQS驱动程序,因为推送的消息不遵循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 事件,这意味着其他监听器可以像往常一样监听它,但它也将使用 broadcastWith 方法定义的有效负载通过 broadcastOn 方法定义的主题进行广播。

广播名称/主题

在 Pub/Sub 上下文中,指定每个发送到 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 进行类似操作,我们建议您从 模型观察器 函数手动触发一些您自己创建的 "broadcastable" 事件。

订阅/监听

配置

一旦安装了该包,并且类似于您为标准 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 监听器并通过该包为您创建的服务提供商关联事件。

注册事件与监听器

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

listen 属性包含所有事件(键)及其监听器(值)的数组。与标准的 Laravel EventServiceProvider 不同,您可以为每个事件定义一个监听器,但您可以添加任意数量的事件到这个数组中,以满足您应用程序的需求。

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

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

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() 方法的函数定义略有不同。我们不会期望传递 Event 类的实例,而是简单地接收 payloadsubject(如果找到的话)。

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

您可以像使用标准的 Laravel 监听器一样对这些监听器进行队列处理。

生成监听器

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

artisan pubsub:make:listener SendShipmentNotification

注意:您仍需要确保在 PubSubEventServiceProvider 中的映射已正确配置。

测试

使用以下命令运行测试:

composer test

变更日志

有关最近更改的更多信息,请参阅我们的 发布记录

贡献

有关详细信息,请参阅 贡献指南

鸣谢

许可

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

旅行不应该破坏地球 🌍

用❤️在 Pod Point 制作