子进程上传文件
最近看的阻塞和异步的资料看的比较多,对基础的概念也理解的深了一点点
因为上次项目中一个接口耗时比较长,所以来优化下
项目本身的逻辑上,填写手机号->生成小程序二维码->上传二维码到七牛->更改数据库邀请码图片->返回API响应
其中 生成二维码和上传二维码到七牛均是一个阻塞网络IO
改进的基本想法是:在还没有创建子进程时生成小程序二维码,得到url,然后创建进程,在主进程 响应API接口信息,子进程继续上传图片到七牛,上传成功修改数据库信息
废话不多说,直接上代码
实例
1 | //getRandChar方法是自己编写的随机字符串方法 |
show
方法为自己封装的响应方法
uploadQrCode 方法
1 | $qiniuAuth = new QiniuAuth(config('qiniu.accessKey'), config('qiniu.secretKey')); |
R_DEVICE_ERROR错误
A PKCS #11 module returned CK R_DEVICE_ERROR, indicating that a problem has
原因大致是在进程中使用了外部的ssl秘钥的原因
https://stackoverflow.com/questions/15466809/libcurl-ssl-error-after-fork
https://stackoverflow.com/questions/26285311/ssl-requests-made-with-curl-fail-after-process-fork
以上是一些参考资料
解决方案我列举几个
pcntl_exec
讲子进程的请求外部资源的代码写到一个php文件,使用pcntl_exec 执行这个 PHP
传参方式可以参考PHP官方文档pcntl-exec子进程不使用curl方式
使用fsockopen,file_get_content使用 socket_create_pair
参考PHP文档socket_create_pair
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31$ary = array();
$strone = 'Message From Parent.';
$strtwo = 'Message From Child.';
if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $ary) === false) {
echo "socket_create_pair() failed. Reason: ".socket_strerror(socket_last_error());
}
$pid = pcntl_fork();
if ($pid == -1) {
echo 'Could not fork Process.';
} elseif ($pid) {
/*parent*/
socket_close($ary[0]);
if (socket_write($ary[1], $strone, strlen($strone)) === false) {
echo "socket_write() failed. Reason: ".socket_strerror(socket_last_error($ary[1]));
}
if (socket_read($ary[1], strlen($strtwo), PHP_BINARY_READ) == $strtwo) {
echo "Recieved $strtwo\n";
}
socket_close($ary[1]);
} else {
/*child*/
socket_close($ary[1]);
if (socket_write($ary[0], $strtwo, strlen($strtwo)) === false) {
echo "socket_write() failed. Reason: ".socket_strerror(socket_last_error($ary[0]));
}
if (socket_read($ary[0], strlen($strone), PHP_BINARY_READ) == $strone) {
echo "Recieved $strone\n";
}
socket_close($ary[0]);
}
- 不使用https
父进程中采用http访问,或者所有子进程中都都采用http访问
PDO错误
PDO::prepare(): send of 66 bytes failed with errno=32 Broken pipe
如果你在子进程使用框架的Model修改数据库,可能会有这个保存
错误原因是框架里的数据库连接是使用的同一个连接
解决方案是在子进程使用原生方式创建一个数据库连接
updateQrCode 方法
1 | $dbConfig = Config::get('database'); |
当然,并不一定都是这个原因
wait_timeout=3600
修改wait_timeout和关闭数据库持久连接都是可能的原因