PHP非阻塞HTTP请求

时间:2019-01-10 07:45:17

标签: php httprequest php-5.5

在PHP中,我正在为我正在从事的项目构建一个挂钩系统。 如果钩子被触发,系统将在数据库中检入需要执行的外部文件。

要达到这个目的,我想使用curl,唯一的问题是curl阻止了其余代码的执行。我想要的只是将HTTP请求发送到给定的URL,而根本不必等待响应。我们不在乎状态。客户应确保代码是否有效。

最大的挑战是我们仍然使用PHP 5.5.9 :(因此,在我们可以升级到PHP 7.2之前,解决方案应该一直在使用它。

是否有实现这一想法或想法?

1 个答案:

答案 0 :(得分:2)

在后台运行单独的进程以发送请求。即使使用异步http请求(无论使用哪种语言),在退出脚本/程序之前,仍必须等待请求完成。

PHP不是Java,每当PHP脚本完成时,所有资源都会被破坏,如果异步http请求尚未完成,它将被取消。

您可以考虑调用“ nohup / path / your_script”来执行一些后台任务。

提示:PHP打开的文件未标记为FD_CLOEXEC,因此,如果您有长期的后台任务,则应先关闭继承的文件描述符,否则会发生资源泄漏。

这里有一些我用来帮助在PHP中运行后台任务的C代码:它首先关闭所有继承的文件描述符,将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;
}