Процесс Laravel CRON или Event отвечает на запрос API через длинный опрос - как оживить сеанс - PullRequest
0 голосов
/ 23 октября 2018

У меня есть маршрут poll в API на сервере Laravel 5.7, где пользователь API может запрашивать любую информацию со времени последнего опроса.

Легкая часть заключается в немедленном ответе на действительный запрос, если естьновая информация return $this->prepareResult($newData);

Если новых данных нет, я сохраняю запрос на опрос в базе данных, и утилита cron может затем проверять раз в минуту все запросы на опрос и отвечать на любые опросы, где данные имеютбыл обновлен.В качестве альтернативы я могу создать прослушиватель событий для обновлений данных и запустить ответ на опрос при обновлении данных.

Я застрял в том, как восстанавливать каждый сеанс в соответствии с устройством, ожидающим обновления.Я могу сохранить или передать идентификатор сеанса, но как мне убедиться, что обработчик задач / событий CRON может ответить на правильный IP-адрес так же, как если бы он был на исходный запрос.Может ли php это сделать?

Я стараюсь избегать веб-сокетов, так как будет иметь много устройств, но с ограниченными обновлениями / взаимодействиями.

Ответы [ 4 ]

0 голосов
/ 02 ноября 2018

Долгий опрос - действующий метод.я думаю, что это плохая идея, чтобы проводить опрос сессией.так как сессия только для оригинального пользователя.Вы можете запустить свой длинный опрос с помощью php cli.Вы можете проверить свое промежуточное программное обеспечение, чтобы разрешить cli только для опроса маршрута.Вы можете использовать pthreads для запуска длинного опроса, используя pthreads через cli.и теперь pthreads v3 разработан безопасно и разумно где угодно, кроме CLI.Вы можете использовать свой cron для запуска вашей темы каждый час.тогда в вашем контроллере вам нужно хранить $ time = time ();чтобы отметить ваше время начала исполнения.затем создайте цикл Dowhile, чтобы зациклить процесс опроса.условие может быть ($ time> time () + 3600) или другое условие.внутри цикла нужно проверить есть ли опрос?если это правда, то запустите его.затем в нижней части строки внутри цикла вам нужно поспать несколько секунд, например, 2 секунды.

на вашем background.php (этот файл выполняется cron)

<?php
error_reporting(-1);
ini_set('display_errors', 1);

class Atomic extends Threaded {
    public function __construct($data = NULL) {
        $this->data = $data;
    }

    private $data;
    private $method;
    private $class;
    private $config;
}

class Task extends Thread {

    public function __construct(Atomic $atomic) {
        $this->atomic = $atomic;
    }

    public function run() {
        $this->atomic->synchronized(function($atomic) 
        {
            chdir($atomic->config['root']);

            $exec_statement = array(
                "php7.2.7",
                $atomic->config['index'],
                $atomic->class,
                $atomic->method
            );

            echo "Running Command".PHP_EOL. implode(" ", $exec_statement)." at: ".date("Y-m-d H:i:s").PHP_EOL;
            $data = shell_exec(implode(" ", $exec_statement));

            echo $data.PHP_EOL;

        }, $this->atomic);
    }

    private $atomic;
}

$config = array(
    "root" => "/var/www/api.example.com/api/v1.1",
    "index" => "index.php",
    "interval_execution_time" => 200
);

chdir($config['root']);

$threads = array();


$list_threads = array(
    array(
        "class" => "Background_workers",
        "method" => "send_email",
        "total_thread" => 2
    ),
    array(
        "class" => "Background_workers",
        "method" => "updating_data_user",
        "total_thread" => 2
    ),
    array(
        "class" => "Background_workers",
        "method" => "sending_fcm_broadcast",
        "total_thread" => 2
    )
);

for ($i=0; $i < count($list_threads); $i++) 
{
    $total_thread = $list_threads[$i]['total_thread'];

    for ($j=0; $j < $total_thread; $j++) 
    { 
        $atomic = new Atomic();
        $atomic->class = $list_threads[$i]['class'];
        $atomic->method = $list_threads[$i]['method'];
        $atomic->thread_number = $j;
        $atomic->config = $config;

        $threads[] = new Task($atomic);
    }
}

foreach ($threads as $thread) {
    $thread->start();
    usleep(200);
}

foreach ($threads as $thread)
    $thread->join();
?>

иэто на вашем контроллере

<?php
    defined('BASEPATH') OR exit('No direct script access allowed');

    class Background_workers extends MX_Controller {

        public function __construct()
        {
            parent::__construct();
            $this->load->database();
            $this->output->enable_profiler(FALSE);
            $this->configuration = $this->config->item("configuration_background_worker_module");
        }

        public function sending_fcm_broadcast() {
            $time_run = time();
            $time_stop = strtotime("+1 hour");

            do{
                $time_run = time();

                modules::run("Background_worker_module/sending_fcm_broadcast", $this->configuration["fcm_broadcast"]["limit"]);

                sleep(2);
            }
            while ($time_run < $time_stop);
        }
    }

это пример кода выполнения от контроллера codeigniter.

0 голосов
/ 30 октября 2018

Long polling требует держать соединение открытым.Это может произойти только через бесконечный цикл checking, чтобы увидеть, существуют ли данные, и затем добавить sleep.

. Нет необходимости оживлять сеанс, так как ответ запускается только для успешных данных.hit.

Обратите внимание, что этот метод требует значительных ресурсов процессора и памяти, так как соединение и работник FPM будут оставаться открытыми до успешного попадания данных.Веб-сокеты - гораздо лучшее решение, независимо от количества устройств и частоты обновлений.

0 голосов
/ 30 октября 2018

Вы можете использовать уведомления .«уведомление браузера» для веб-клиентов и уведомление FCM и APN для мобильных клиентов.

Другой вариант - использование SSE (события, отправленные сервером).Это соединение типа сокета, но через http.Клиент отправляет обычный запрос, и сервер может просто ответить клиенту несколько раз и в любое время, если клиент доступен (в том же запросе, который был отправлен).

0 голосов
/ 23 октября 2018

Клиенты запрашивают обновления, API не запускают обновления.

REST API, как предполагается, не имеют состояния, поэтому попытка отслеживания серверной части идет вразрез с REST.
Если конкретно ответить на ваш вопрос, еслиВы не хотите использовать веб-сокеты, клиентскому приложению придется продолжать опрашивать конечную точку, пока данные не станут доступны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...