PHP Неблокирующий http-запрос

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

Чтобы достичь этого, я думал об использовании curl, единственная проблема заключается в том, что curl блокирует выполнение остального кода. Я хочу просто отправить HTTP-запрос на указанный URL-адрес и вообще не ждать ответа. Нам не важен статус. Клиент должен убедиться, что код работает.

Большая проблема заключается в том, что мы все еще используем PHP 5.5.9 :( Так что решение должно работать с ним, пока мы не сможем перейти на PHP 7.2.

Любые идеи или толчки для достижения этого?


person Ronald Werkhoven    schedule 10.01.2019    source источник
comment
Возможный дубликат асинхронного запроса curl в PHP   -  person Justinas    schedule 10.01.2019
comment
Запустите отдельный процесс в фоновом режиме, чтобы отправить запрос. Даже если вы используете асинхронный http-запрос (независимо от того, какой язык вы используете), вы все равно должны дождаться завершения запроса, прежде чем выйти из своего скрипта/программы.   -  person shawn    schedule 10.01.2019
comment
Сначала обновите PHP. 5.5 перестал получать исправления безопасности два с половиной года назад! Если бы я был вашим клиентом, я бы не имел с вами дело.   -  person Bart Friederichs    schedule 10.01.2019
comment
@BartFriederichs расскажите мне об этом, было бы неплохо, если бы вы убедили менеджера проекта, что это больше не работает :P   -  person Ronald Werkhoven    schedule 10.01.2019
comment
Могут быть причины не обновляться, но если это общедоступный сервис, то их нет.   -  person Bart Friederichs    schedule 10.01.2019
comment
@shawn, не могли бы вы изменить комментарий на решение, чтобы я мог пометить его как решение.   -  person Ronald Werkhoven    schedule 10.01.2019
comment
@RonaldWerkhoven Я обновил более подробную информацию. Рад, что ты со мной согласен :D   -  person shawn    schedule 10.01.2019
comment
может быть, какая-то система очередей поможет, например, rabbitmq   -  person Robert    schedule 10.01.2019
comment
@RonaldWerkhoven, вы все равно должны дождаться ответа клиента. Как правило, все издатели веб-перехватчиков (например, ваша система) полагаются на то, что потребитель возвращает HTTP 200, если нет, вы должны считать его недоставленным. Лучший способ сделать это в масштабе — использовать какую-либо очередь (СУБД или Rabbitmq) и не удалять элемент из очереди, пока вы не будете уверены, что он был использован.   -  person Borislav Sabev    schedule 11.01.2019


Ответы (1)


Запустите отдельный процесс в фоновом режиме, чтобы отправить запрос. Даже если вы используете асинхронный http-запрос (независимо от того, какой язык вы используете), вы все равно должны дождаться завершения запроса, прежде чем выйти из своего скрипта/программы.

PHP - это не Java, каждый раз, когда PHP-скрипт завершается, все ресурсы будут уничтожены, если асинхронный http-запрос не завершен, он будет отменен.

Вы можете вызвать «nohup /path/your_script» для выполнения некоторых фоновых задач.

Подсказка: открытые файлы PHP не помечаются как FD_CLOEXEC, поэтому, если у вас есть длительная фоновая задача, вы должны сначала закрыть унаследованные файловые дескрипторы, иначе произойдет утечка ресурсов.

Вот несколько кодов C, которые я использовал для запуска фоновых задач в PHP: он сначала закрывает все унаследованные файловые дескрипторы, перенаправляет stdout/stderr в /dev/null, затем переходит в фоновый режим (например, nohup)

/*
gcc -m32 bgexec.c  -o bgexec
*/
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

void close_fds()
{
    char buf[256];
    struct dirent *dp;
    snprintf(buf, 255, "/proc/%i/fd/", getpid());
    DIR *dir = opendir(buf);
    while ((dp = readdir(dir)) != NULL) {
        if(dp->d_name[0] && dp->d_name[0] != '.') {
            //printf("fd: %s\n", dp->d_name);
            close(atoi(dp->d_name));
        }
    }
    closedir(dir);
}

int main(int argc, char *argv[])
{
    int pid;
    signal(SIGCLD, SIG_IGN);   // no defunct when no wait();
    if (argc < 2)
        return fprintf(stderr, "No arguments given\n"), 1;

    /* Fork it */
    pid = fork();
    if(pid < 0)
        return fprintf(stderr, "Couldn't fork\n"), 127;

    if (pid == 0) {
        /* Child */
        setsid();
        umask ( 0 ); /* clear file mode creation mask */
        close_fds();

        int fd = open("/dev/null", O_RDWR);
        dup2(0, 1);
        dup2(0, 2);
        signal(SIGHUP, SIG_IGN);   // no hup
        signal(SIGCLD, SIG_DFL);   // keep away from 'exec' returns ECHILD
        /* Execute it */
        execv(argv[1], &argv[1]);
        exit(127);
    }
    return 0;
}
person shawn    schedule 10.01.2019