itprojektrepo / 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
This package is not auto-updated.
Last update: 2024-09-20 08:00:37 UTC
README
酒吧
类似于Pusher,此包提供Laravel Broadcasting驱动,用于AWS SNS(简单通知服务)和AWS EventBridge以发布服务器端事件。
我们理解Broadcasting通常用于“广播”您的服务器端Laravel Events通过WebSocket连接到您的客户端JavaScript应用程序。然而,我们认为这种利用广播的方法对于Pub/Sub架构很有意义,其中应用程序希望将服务器端事件广播到外部世界,关于刚刚发生的事情。
在这种情况下,“频道”可以与使用SNS驱动时的“主题”以及使用EventBridge驱动时的“事件总线”相类比。
订阅
这部分相当直接,我们只需监听推送到SQS队列的消息并对它们采取行动即可。这里唯一的区别是我们不使用默认的Laravel SQS驱动,因为推送的消息不遵循从Laravel应用程序推送的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 事件,这意味着其他监听器可以像往常一样监听它,但它也将通过使用 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
特性并遵循官方文档。
您可以在模型上使用 broadcastOn
、broadcastWith
和 broadcastAs
方法来自定义主题名称、负载数据和主题。
注意:模型广播仅在 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。
鸣谢
- laravel-sns-broadcaster 提供了一些灵感。
- laravel-sqs-sns-subscription-queue 提供了更多灵感。
- Laravel 包开发 文档由 John Braun 编写。
- Pod Point
- 所有贡献者
许可证
MIT 许可证(MIT)。有关更多信息,请参阅 许可证文件。
旅行不应破坏地球 🌍
用 ❤️ 制作于 Pod Point