首页 编程开发laravel广播系统实现任务状态推送

laravel广播系统实现任务状态推送

分类:编程开发
字数: 3813
评论: 0
阅读: 942
摘要:ajax轮询消耗服务器资源,laravel广播系统实时通知

Laravel Websockets 需要laravel 5.7+,所以需要以后更新了laravel之后才能做这个功能。

目前产品的任务系统靠ajax轮询实现,每5秒刷新一次数据,这样的做法每次都需要消耗服务器资源,而且会影响用户体验。
使用laravel的广播系统可以做到由服务器实时通知客户端更新任务状态,且不需要轮询,底层是websockets技术。

一. 服务端安装

1. 安装服务器端广播驱动程序

广播驱动程序是用来处理ws/wss请求, 本次使用的是: Laravel Websockets
Laravel Websockets 需要laravel 5.7+
通过composer可以安装:

composer require beyondcode/laravel-websockets

生成websockets配置文件config/websockets.php:

php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"

启动程序进程:线上可以添加到后台运行

php artisan websockets:serve

2. 配置广播系统

  1. config/broadcasting.php 配置文件中包含每个驱动程序的配置示例。

  2. Provider: 在广播事件之前,首先需要注册 App\Providers\BroadcastServiceProvider。在 config/app.php 配置文件的 providers 数组中取消注释。这个BroadcastServiceProvider包含注册广播授权路由和回调所需的代码。

  3. 队列配置:您还需要配置和运行 queue worker。所有事件广播都是通过排队作业完成的,因此您的应用程序的响应时间不会受到广播事件的严重影响。

  4. 使用 Composer 包管理器安装 Pusher Channels PHP SDK

    composer require pusher/pusher-php-server
  5. 在.env中配置pusher相关配置

    BROADCAST_DRIVER=pusher
    ...
    PUSHER_APP_ID=my_pusher
    PUSHER_APP_KEY=my_pusher
    PUSHER_APP_SECRET=my_pusher
    PUSHER_HOST=127.0.0.1
    PUSHER_PORT=6001
    PUSHER_SCHEME=http
    PUSHER_APP_CLUSTER=mt1

3. TaskStateEvent

新建任务状态事件, 注意需要集成ShouldBroadcast,事件创建了一个规则为task.{user_id的md5}的私人频道。

<?php

namespace App\Events;

use App\Models\AnalysisTaskModel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class TaskStateEvent implements ShouldBroadcast
{
    public $task;

    public function __construct($id)
    {
        $this->task = AnalysisTaskModel::query()->find($id);
    }

    public function broadcastOn()
    {
        return new PrivateChannel('task.'. md5($this->task->user_id));
    }

    /**
     * 获取要广播的数据。
     *
     * @return array
     */
    public function broadcastWith()
    {
        return ['id' => $this->task->id, 'state' => $this->task->state];
    }
}

4. 配置频道授权

config/channels.php中添加:

Broadcast::channel('task.{auth}', function ($user, $auth) {
    return md5($user->id) === $auth;
});

5. 通知客户端接口

任务状态由python改变,需要给python提供一个接口,来让python告诉php某个任务的状态发生了改变。
php添加路由:

Route::GET('task/state', 'AnalysisTask@stateChange');

在AnalysisTask控制器中新建函数:
函数接收任务id作为参数,并传递给事件系统。

/**
* 通知客户端,任务状态改变
* @param Request $request
* @return void
*/
public function stateChange (Request $request) {
  event(new TaskStateEvent($request->get('id')));
}

python可以执行curl来访问该接口:

# shell
curl http://xxxxxxx/api.php/task/state?id=165

二. 前端安装

1. Laravel Echo / pusher-js

Laravel Echo 是一个 JavaScript 库,可以轻松订阅频道和收听服务器端广播驱动程序广播的事件。 你可以通过 NPM 包管理器安装 Echo。在此示例中,我们还将安装 pusher-js 包,因为我们将使用 Pusher Channels 广播器:

# npm
npm install --save-dev laravel-echo pusher-js

# yarn
yarn add laravel-echo pusher-js

2. 修改代码

在任务列表页面创建Echo实例:

import Echo from 'laravel-echo'
import Pusher from 'pusher-js'

# 以下可以写到method中  
const client = new Pusher('my_pusher', {
  forceTLS: document.location.protocol === 'https:',
  wsHost: window.location.hostname,
  wssHost: window.location.hostname,
  wsPort: 6001,
  wssPort: 6001,
  auth: {
    headers: {}
  },
  disableStats: true,
  cluster: 'mt1',
  authEndpoint: '/api.php/broadcasting/auth'
})
this.echo = new Echo({
  broadcaster: 'pusher',
  client: client
})
console.log(this.userInfo)
const auth = this.userInfo.auth
this.echo.private(`task.${auth}`)
  .listen('TaskStateEvent', (e) => {
    console.log(e)
    this.list.map(item => {
      if (item.id === e.id) {
        item.state = e.state
      }
    })
  })

在mounted中设置3秒后启动,原因是可能不小心点击到本页面(如何确保userInfo一定存在?)

this.kit = setTimeout(this.connectWebSockets, 3000)

在beforeDestroy钩子中销毁定时器并离开广播频道:

const auth = this.userInfo.auth
this.echo.leave(`task.${auth}`)
if (this.kit) {
  clearTimeout(this.kit)
}

三、参考链接

  1. 由浅入深:基于 Laravel Broadcast 实现 WebSocket C/S 实时通信
  2. laravel:广播系统
  3. laravel-websockets Documention
文章发布于: 2023-12-20 09:26:00

扫描二维码,在手机上阅读