微服务架构中如何处理Laravel Notification功能?
Laravel微服务架构下通知服务的实现方案
在微服务架构中,Notification服务不需要访问User服务的完整模型,只需要获取发送通知必需的用户数据即可。下面是具体的实现思路和示例:
核心思路
微服务间通过API传递最小化的用户通知数据(如邮箱、推送Token、手机号等),Notification服务内部创建一个极简的"通知收件人"类,而非重复定义完整的User模型,以此适配Laravel的Notifiable特性。
具体实现示例
1. Notification服务中创建极简的收件人类
这个类仅保留通知渠道所需的字段,并实现Notifiable trait要求的路由方法:
// app/Models/NotificationRecipient.php namespace App\Models; use Illuminate\Notifications\Notifiable; class NotificationRecipient { use Notifiable; public int $id; public string $email; public ?string $fcm_token; public function __construct(array $userData) { $this->id = $userData['id']; $this->email = $userData['email']; $this->fcm_token = $userData['fcm_token'] ?? null; } // 定义邮件通知的接收地址 public function routeNotificationForMail($notification): string { return $this->email; } // 定义FCM推送的Token public function routeNotificationForFcm($notification): ?string { return $this->fcm_token; } // 如需支持短信,可添加对应路由方法 // public function routeNotificationForSms($notification): string // { // return $this->phone; // } }
2. 创建常规的Laravel通知类
和单体架构中的写法一致,定义多渠道的通知内容:
// app/Notifications/OrderShipped.php namespace App\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\FcmMessage; class OrderShipped extends Notification implements ShouldQueue { use Queueable; private array $orderDetails; public function __construct(array $orderDetails) { $this->orderDetails = $orderDetails; } public function via($notifiable): array { // 根据收件人数据动态选择渠道(比如无FCM Token则只发邮件) $channels = ['mail']; if ($notifiable->fcm_token) { $channels[] = 'fcm'; } return $channels; } public function toMail($notifiable): MailMessage { return (new MailMessage) ->subject('您的订单已发货') ->line('订单号: ' . $this->orderDetails['order_id']) ->line('预计3个工作日内送达') ->action('查看物流', url("/track/{$this->orderDetails['tracking_no']}")); } public function toFcm($notifiable): FcmMessage { return (new FcmMessage) ->content([ 'title' => '订单发货通知', 'body' => "您的订单#{$this->orderDetails['order_id']}已发出,点击查看物流", ]) ->data([ 'order_id' => $this->orderDetails['order_id'], 'tracking_no' => $this->orderDetails['tracking_no'], ]); } }
3. Notification服务提供API接口接收通知请求
暴露接口让其他服务(如User服务)触发通知:
// routes/api.php use Illuminate\Http\Request; use App\Models\NotificationRecipient; use App\Notifications\OrderShipped; Route::post('/notifications/order-shipped', function (Request $request) { // 验证请求参数 $validated = $request->validate([ 'user' => 'required|array', 'user.id' => 'required|integer', 'user.email' => 'required|email', 'user.fcm_token' => 'nullable|string', 'order_details' => 'required|array', 'order_details.order_id' => 'required|string', 'order_details.tracking_no' => 'required|string', ]); // 创建收件人实例并发送通知 $recipient = new NotificationRecipient($validated['user']); $recipient->notify(new OrderShipped($validated['order_details'])); return response()->json(['status' => 'notification_sent']); });
4. User服务调用Notification服务的接口
在User服务中,当需要触发通知时,调用上述API并传递必要的用户和业务数据:
// User服务中触发通知的代码示例 use Illuminate\Support\Facades\Http; use App\Models\User; $user = User::find(1); $orderDetails = [ 'order_id' => 'ORD-20240501001', 'tracking_no' => 'TRK-789456', ]; // 调用Notification服务的API Http::post('http://notification-service/api/notifications/order-shipped', [ 'user' => [ 'id' => $user->id, 'email' => $user->email, 'fcm_token' => $user->fcm_token, ], 'order_details' => $orderDetails, ]);
额外建议
- 可以使用DTO类(如
UserNotificationData)来规范服务间传递的用户数据,避免参数混乱 - 启用Laravel队列处理通知发送,避免阻塞主服务的请求响应
- 若需保证数据一致性,可考虑在User服务的用户信息变更时,主动同步通知所需字段到Notification服务的缓存或数据库中
内容的提问来源于stack exchange,提问作者Hanie Asemi
相关产品推荐
相关产品推荐

