Рубрики
Uncategorized

Laravel использует вариант разработки проекта swool 2 (сценарии активного разделения серверной части для отправки сообщений в интерфейс)

Автор оригинала: David Wong.

Недавно мы выполнили проект с использованием свул , который проектирует передачу информации на передний конец интерфейса и мониторинг состояния пользователей, не заходящих на посадку. Вот мой опыт из этого. Пожалуйста, оставьте комментарий по поводу улучшения.

анализ требований

Давайте предположим, что есть какое-то требование. Я нажимаю на кнопку 1 на задней панели, и на домашней странице появляется надпись “кнопка 1 активирована на задней панели”. Кнопка 2 нажимается на задней панели, и на странице списка появляется надпись “Кнопка 2 активируется на задней панели”. Переходите на разные страницы в соответствии с разными сценариями.

Идеи Кода

  • Свул фд

Клиентский браузер открывает или обновляет интерфейс и генерирует дескриптор процесса в службе swool fd Каждый раз, когда на странице браузера есть код JS, который открывает ссылку на websocket, он генерирует, и каждый раз, когда он обновляется, он открывается перед закрытием fd Для создания нового, новый будет сгенерирован при закрытии интерфейса. Правила генерации Swool fd являются инкрементными с 1.

  • Хранилище хэшей Redis FD

Давайте настроим ключ для swool:данные типа хэша fds Redis, fd Для хэш-полей мы храним информацию о параметрах URL-адреса в интерфейсном запросе websocket для значения каждого поля (в соответствии с гибкостью самой бизнес-сложности я приведу идентификатор сеанса по URL-адресу в проекте). Каждый раз, когда ссылка открывает сервис swool, мы храним ее информацию, и каждый раз, когда страница закрывается, мы очищаем ее поля. Хранить в redis следующим образом

  • Запуск под-сценария push

    Когда запуск выполняется в интерфейсе, служба HTTP swool запрашивается через фоновый завиток, и служба HTTP swool распределяется для соответствующей логической обработки в соответствии с параметрами, которые вы передаете мне. Например, запрос curl 127.0.0.1:9502 страница=назад&функция=pushHomeLogic&токен=123456 Мы можем зависеть от входящих функций Параметров, которые распространяются на соответствующую логическую обработку в фоновом режиме. Если распространяется в pushHomeLogic Метод. Он реализует свою собственную логику. Чтобы предотвратить чрезмерное если |/еще , а также Для каждой операции Мы используем замыкания. call_user_func Методы следующие.

Полный код

Логика кода скрипта Swoop

php

namespace App\Console\Commands;

use Closure;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;

class SwooleDemo extends Command
{
    // Command Name
    protected $signature = 'swoole:demo';
    // Command description
    Protected $description = this is a test demo for swoole websocket;
    // swoole websocket service
    private static $server = null;

    public function __construct()
    {
        parent::__construct();
    }

    // Entrance
    public function handle()
    {
        $this->redis = Redis::connection('websocket');
        $server = self::getWebSocketServer();
        $server->on('open',[$this,'onOpen']);
        $server->on('message', [$this, 'onMessage']);
        $server->on('close', [$this, 'onClose']);
        $server->on('request', [$this, 'onRequest']);
        This - > line ("swoole service started successfully...");
        $server->start();
    }

    // Access to services
    public static function getWebSocketServer()
    {
        if (!(self::$server instanceof \swoole_websocket_server)) {
            self::setWebSocketServer();
        }
        return self::$server;
    }
    // Service Start Settings
    protected static function setWebSocketServer():void
    {
        self::$server  = new \swoole_websocket_server("0.0.0.0", 9502);
        self::$server->set([
            'worker_num' => 1,
            'heartbeat_check_interval'=> 60, // 60 second detection once
            'heartbeat_idle_time'=> 121, // 121 seconds inactive
        ]);
    }

    // Open the swoole websocket service callback code
    public function onOpen($server, $request)
    {
        if ($this->checkAccess($server, $request)) {
            Self:: $server - > push ($request - > fd, xss_json (["code"=> 200, "message"=> "success of opening swoole service");
        }
    }
    // Send message callback code to swoole websocket
    public function onMessage($server, $frame)
    {

    }
    // HTTP requests swoole websocket callback code
    public function onRequest($request,$response)
    {
        if ($this->checkAccess("", $request)) {
            $param = $request->get;
            // Distribution Processing Request Logic
            if (isset($param['func'])) {
                if (method_exists($this,$param['func'])) {
                    call_user_func([$this,$param['func']],$request);
                }
            }
        }
    }

    // websocket closes callback code
    public function onClose($serv,$fd)
    {
        $this->redis->hdel('swoole:fds', $fd);
        $this - > line ("client {$fd} closed");
    }


    // Verify the validity of client connections, invalid connections do not allow connections
    public function checkAccess($server, $request):bool
    {
        $bRes = true;
        if (!isset($request->get) || !isset($request->get['token'])) {
            self::$server->close($request->fd);
            $this - > line ("incomplete interface validation fields");
            $bRes = false;
        } else if ($request->get['token'] != 123456) {
            $this - > line ("interface validation error");
            $bRes = false;
        }
        $this->storeUrlParamToRedis($request);
        return $bRes;
    }

    // Store the URL of each interface open websocket
    public function storeUrlParamToRedis($request):void
    {
        // Store the information in the request URL
        $sContent = json_encode(
            [
                'page' => $request->get['page'],
                'fd' => $request->fd,
            ], true);
        $this->redis->hset("swoole:fds", $request->fd, $sContent);
    }

    /**
     * @param $request
     *@ See Loop Logic Processing
     */
    public function eachFdLogic(Closure $callback = null)
    {
        foreach (self::$server->connections as $fd) {
            if (self::$server->isEstablished($fd)) {
                $aContent = json_decode($this->redis->hget("swoole:fds",$fd),true);
                $callback($aContent,$fd,$this);
            } else {
                $this->redis->hdel("swoole:fds",$fd);
            }
        }
    }
    // Push Logic Processing to Home Page
    public function pushHomeLogic($request)
    {
        $callback = function (array $aContent,int $fd,SwooleDemo $oSwoole)use($request) {
            if ($aContent && $aContent['page'] == "home") {
                $aRes ['message']= "Back-end pressed button 1";
                $aRes['code'] = "200";
                $oSwoole::$server->push($fd,xss_json($aRes));
            }
        };
        $this->eachFdLogic($callback);
    }
    // Push Logical Processing to List Pages
    public function pushListLogic($request)
    {
        $callback = function (array $aContent,int $fd,SwooleDemo $oSwoole)use($request) {
            if ($aContent && $aContent['page'] == "list") {
                $aRes ['message']= "The back end pushed button 2";
                $aRes['code'] = "200";
                $oSwoole::$server->push($fd,xss_json($aRes));
            }
        };
        $this->eachFdLogic($callback);
    }

    // Start the websocket service
    public function start()
    {
        self::$server->start();
    }
}

Код контроллера

method() == 'POST') {
           $this->curl_get($this->getUrl());
           Return json_encode (['code'= > 200,'message'= > success]);
        } else {
            return view("back");
        }

    }
    // Get the swoole websocet service address to request
    public function getUrl():string
    {
        // Method of Domain Name Port Requesting Swoole Service
        $sBase = request()->server('HTTP_HOST');
        $iPort = 9502;
        $sFunc = request()->post('func');
        $sPage = "back";
        return $sBase.":".$iPort."?func=".$sFunc."&token=123456&page=".$sPage;
    }
    // curl push
    public function curl_get(string $url):string
    {
        $ch_curl = curl_init();
        curl_setopt ($ch_curl, CURLOPT_TIMEOUT_MS, 3000);
        curl_setopt($ch_curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt ($ch_curl, CURLOPT_HEADER,false);
        curl_setopt($ch_curl, CURLOPT_HTTPGET, 1);
        curl_setopt($ch_curl, CURLOPT_RETURNTRANSFER,true);
        curl_setopt ($ch_curl, CURLOPT_URL,$url);
        $str  = curl_exec($ch_curl);
        curl_close($ch_curl);
        return $str;
    }
}

Код страницы JS

  • Страница внутреннего управления





    
    < title > back-end interface 
    







  • домашняя страница





    
    < title > swoole homepage 
    


This is the home page.

  • Страница списка





    
    < title > swoole list page 
    


swoole list page

Эффект интерфейса

Управление фоном нажмите кнопку 1

Внутренний интерфейс нажмите кнопку 2