foodticket / laravel-aws-pubsub
一个Laravel广播驱动程序和队列驱动程序,利用AWS SNS、EventBridge和SQS广播和监听发布的事件。
Requires
- php: ^7.3|^8.0
- ext-json: *
- aws/aws-sdk-php: ^3.155
- illuminate/support: ^8.52|^9.0|^10.0|^11.0
Requires (Dev)
- orchestra/testbench: ^6.0|^7.0|^8.0|^9.0
README
酒吧
类似于Pusher,此包提供了Laravel Broadcasting驱动程序,用于AWS SNS(简单通知服务)和AWS EventBridge,以便发布服务器端事件。
我们理解Broadcasting通常用于将您的服务器端Laravel 事件通过WebSocket连接广播到您的客户端JavaScript应用程序。然而,我们认为这种利用广播的方法对于Pub/Sub架构是有意义的,在这种架构中,应用程序希望向外部世界广播关于刚刚发生的事情的服务器端事件。
在这种情况下,当使用SNS驱动程序时,“通道”可以理解为“主题”,而当使用EventBridge驱动程序时,“事件总线”可以理解为“通道”。
订阅
这部分相当直接,我们只需要监听推送到SQS队列的消息并对其采取行动。这里唯一的区别是我们不使用默认的Laravel SQS驱动程序,因为推送的消息不遵循Laravel应用程序推送的经典的JSON有效负载作业/事件。SNS的消息更简单。
先决条件
- 在两个Laravel应用程序上安装并配置了此包:发布者和订阅者
- 至少一个SQS队列 - 每个订阅Laravel应用程序一个队列
- 至少一个SNS主题
- 在您的SNS主题和SQS队列之间配置了一个SQS订阅,并禁用了“原始消息交付”
- 配置了相关的访问策略,尤其是如果您想能够直接从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
特性并遵循官方文档。
您可以在模型上使用 broadcastOn
、broadcastWith
和 broadcastAs
方法来自定义主题名称、有效负载和主题。
注意:模型广播仅在 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 类的实例,而是简单地接收 payload
和 subject
(如果找到的话)。
/** * Handle the event. * * @return void */ public function handle(array $payload, string $subject = '') { // ... }
您可以像使用标准的 Laravel 监听器一样对这些监听器进行队列处理。
生成监听器
我们还提供了一个方便的命令来为您生成这些类。
artisan pubsub:make:listener SendShipmentNotification
注意:您仍需要确保在 PubSubEventServiceProvider
中的映射已正确配置。
测试
使用以下命令运行测试:
composer test
变更日志
有关最近更改的更多信息,请参阅我们的 发布记录。
贡献
有关详细信息,请参阅 贡献指南。
鸣谢
- laravel-sns-broadcaster 提供了一些灵感
- laravel-sqs-sns-subscription-queue 提供了更多灵感
- Laravel 包开发 文档由 John Braun 提供
- Pod Point
- 所有贡献者
许可
MIT 许可证(MIT)。有关更多信息,请参阅 许可文件。
旅行不应该破坏地球 🌍
用❤️在 Pod Point 制作