描述
php 浏览器请求服务端,服务端用shell_exec去触发php脚步程序执行。当脚本程序被执行时,出现了阻塞情况,客户端的请求必须等到脚本程序里面退出。
脚本程序大致内容
脚本程序大致是使用php stream系列函数去连接某个tcp协议的服务端,收到服务端相应的数据就退出。
客户端相关相关代码
if (Yii::$app->request->isAjax) {
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$model = $this->findModel($id);
if (!empty($model->pdf_path)) {
return ['statusCode' => 300, 'message' => '该文件已被转换过pdf!'];
}
$model->sendPreview();
return ['statusCode' => 200, 'message' => '请求发送成功!'];
}
//sendPreview代码
$retArr = [];
$retVal = '';
exec('php ' . Yii::$app->basePath . '/../yii init/office-to-pdf ' . $this->id, $retArr, $retVal);
脚本程序相关代码
// 建立socket连接
$client = stream_socket_client($address, $errno, $errmsg, $config['stream_timeout']);
if (!$client) {
exit("$errmsg\n");
}
// 设置成阻塞
stream_set_blocking($client, $config['blocking_mode']);
while (true) {
$res1 = explode("\n", fread($client, 216));
$res = json_decode($res1[0], true);
$current_ftell = null;
if ($res) {
if ( $config['transfer_state'][4] === $res['code']) {
echo 'The file upload failed ';
if (isset($res['msg'])) echo $res['msg'];
echo "\n";
break;
}
...
}
模糊概念
这里是因为脚本里面的stream_set_blocking($client, $config['blocking_mode']);和while(true)导致的?
我的想法:客户端发起一个请求到nginx,nginx在和php-fpm通讯,php-fpm开启一个一个进程执行代码
那exec触发php脚本,是在php cli处理的。这里php-fpm 和cli有关联?
求解
知识能力有限,但是求甚解,秉持“知其然,知其所以然”,请大家赐教
回答
你的问题和php-cli没有任何联系,不要走弯路。
exec 是同步阻塞动作,如果 exec 调用的脚本卡住了,那么整个 php 就都会卡住。
你的需求应该是上传doc文件并在服务器端转换成pdf,这个动作本身就很耗时。业界都是上传后直接结束上传流程,返回用户状态后就结束。后台异步做 doc2pdf 。
有人回答吗?
你提的问题有点混乱,你设置了阻塞函数,当然会阻塞。如果你用cli运行命令,那就不会走阻塞函数。但是本身PHP就是阻塞的,你执行文件转换的时候就会阻塞啊。
至于fpm和cli的关系,你可以看这个回答https://segmentfault.com/q/10…
服务器 CLI 挂队列。把任务 push 进队列,给前台一个回调地址用来查询结果。