PHP 非阻塞http请求
PHP Non blocking http request
在 PHP 中,我正在为我现在正在进行的项目构建一个挂钩系统。
如果触发了钩子,系统将在数据库中检查需要执行的外部文件。
为了实现这一点,我正在考虑使用 curl,唯一的问题是 curl 会阻止其余代码的执行。我想要的是只向给定的 URL 发送一个 HTTP 请求,而不必等待响应。我们不关心状态。确保代码正常工作取决于客户。
最大的挑战是我们仍然使用 PHP 5.5.9 :( 所以解决方案应该使用它,直到我们可以升级到 PHP 7.2
有什么想法或建议可以实现这一目标吗?
运行 一个独立的后台进程来发送请求。即使您使用异步 http 请求(无论您使用什么语言),您仍然必须等待请求完成才能退出 script/program。
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;
}
在 PHP 中,我正在为我现在正在进行的项目构建一个挂钩系统。 如果触发了钩子,系统将在数据库中检查需要执行的外部文件。
为了实现这一点,我正在考虑使用 curl,唯一的问题是 curl 会阻止其余代码的执行。我想要的是只向给定的 URL 发送一个 HTTP 请求,而不必等待响应。我们不关心状态。确保代码正常工作取决于客户。
最大的挑战是我们仍然使用 PHP 5.5.9 :( 所以解决方案应该使用它,直到我们可以升级到 PHP 7.2
有什么想法或建议可以实现这一目标吗?
运行 一个独立的后台进程来发送请求。即使您使用异步 http 请求(无论您使用什么语言),您仍然必须等待请求完成才能退出 script/program。
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;
}