84669 人が学習中
152542 人が学習中
20005 人が学習中
5487 人が学習中
7821 人が学習中
359900 人が学習中
3350 人が学習中
180660 人が学習中
48569 人が学習中
18603 人が学習中
40936 人が学習中
1549 人が学習中
1183 人が学習中
32909 人が学習中
在我收到请求处理后有一个很耗时的需要请求微信接口的操作,需要处理很多订单调用微信接口。想在echo之后再执行这些操作。消息队列需要给服务器安装扩展如memcacheq之类的,我没有操作服务器的权利,想用代码解决。可不可以实现消息队列,有没有大神给个例子我对队列操作一窍不通。我看到了也可以用fsockopen 实现,这样跟消息队列机制有什么区别。
学习是最好的投资!
//程序被阻塞10秒 shell_exec('timeout 10 vmstat 1 >/dev/null 2>&1 &'); //程序不会被阻塞 pclose(popen('timeout 10 vmstat 1 >/dev/null 2>&1 &', 'r')); //因此可以异步执行任务 pclose(popen("timeout 60 php /path/to/task.php '$arg' >/dev/null 2>&1 &", 'r'));
其中变量$arg是传递给脚本task.php的参数,task.php里通过$argv[1]拿到这个参数.timeout 60 表示task.php脚本的最大执行时间60秒,不需要的话可以去掉.pclose(popen())实现异步的本质是打开一个进程去执行阻塞代码,适用于不要求执行完成后自动返回结果(回调)的异步场景.
字符串参数$arg可以用单引号括起来,可以避免一些空格的影响,但还是有缺陷.为了避免Shell注入(对比SQL注入),字符串参数最好还是serialize序列化到文件,然后给脚本task.php传文件路径这个参数,让task.php自己读文件unserialize反序列化拿数据.文件名应该做到唯一,比如可以是用户ID+进程PID+时间随机数:
$filename = md5(uniqid($uid.'_'.getmypid().'_'.mt_rand().'_', true));
PHP-FPM提供的函数fastcgi_finish_request可以冲刷(flush)所有响应的数据给客户端并结束请求.这使得客户端结束连接后,能够继续执行不需要输出给用户的代码,比如生成缓存,但仍会阻塞当前FPM工作进程.http://php.net/manual/zh/func...
fastcgi_finish_request
fsockopen 意思就是发出一个请求(类似curl),但是不等待返回结果。
所以用fsockopen 也可以,你echo之后fsockopen 请求一下本地上对微信接口的操作,就可以了
其中变量$arg是传递给脚本task.php的参数,task.php里通过$argv[1]拿到这个参数.
timeout 60 表示task.php脚本的最大执行时间60秒,不需要的话可以去掉.
pclose(popen())实现异步的本质是打开一个进程去执行阻塞代码,
适用于不要求执行完成后自动返回结果(回调)的异步场景.
字符串参数$arg可以用单引号括起来,可以避免一些空格的影响,但还是有缺陷.
为了避免Shell注入(对比SQL注入),字符串参数最好还是serialize序列化到文件,
然后给脚本task.php传文件路径这个参数,让task.php自己读文件unserialize反序列化拿数据.
文件名应该做到唯一,比如可以是用户ID+进程PID+时间随机数:
PHP-FPM提供的函数
fastcgi_finish_request
可以冲刷(flush)所有响应的数据给客户端并结束请求.这使得客户端结束连接后,能够继续执行不需要输出给用户的代码,比如生成缓存,但仍会阻塞当前FPM工作进程.http://php.net/manual/zh/func...
fsockopen 意思就是发出一个请求(类似curl),但是不等待返回结果。
所以用fsockopen 也可以,你echo之后fsockopen 请求一下本地上对微信接口的操作,就可以了