我有一个工作人员,它使用 pcntl_fork()
跨越新工作,我想在每个 child 中重复使用相同的连接,而不需要在每个 child 中每次都重新连接,目标是获得巨大的性能提升。
- 在父级中,我连接到 SMTP 服务,然后 fork 出一个子级。
- 第一个 child 成功使用 SMTP 流并可以发送消息。
- 当 child 结束时套接字自动关闭。我既不调用任何关闭函数也不调用析构函数,您可以在随附的 repo 示例中看到。
- 在此之后, parent 和下一个 child 都不能再使用打开的套接字。
我想防止第 3 个问题,以便下一个 child 可以重用套接字,而无需再次重新连接,因为您知道 SMTP 协议(protocol)很繁琐,重新连接需要时间。 SMTP 服务器可能是 sendmail/sendgrid/Gmail,我尝试了多个提供商,问题出在我的 PHP 而不是 SMTP 协议(protocol)。
我读到信号可能会导致流关闭。有什么办法可以防止这种情况发生。
我有哪些选择?
我正在使用 PHPMailer , 我删除了 close from destructor .我激活了 SMTPKeepAlive
但没有帮助,如您在随附的 repo 示例中所见。如果重要,我使用的是 PHP 5.4
更新 1
我在这个公共(public)仓库中添加了示例代码:https://github.com/pentium10/php_stream_socket_test您可以在 http://www.dispostable.com/inbox/test/ 查看一次性收件箱
您可以在存储库的自述文件中找到输出和 SMTP 响应。我确认从 fork/child/exit 调用中删除任何内容,该示例有效并一个接一个地发送多条消息。
最佳答案
在对您提供的代码进行一些调查之后,您的问题似乎是在您启用 TLS 时出现的。
如果禁用以下行:
$mail->SMTPSecure = 'tls';
您的代码将按预期工作(只要您的 smtp 服务器接受不安全的连接)。
所以这绝对不是套接字或 fork 问题,而可能是违反 TLS 协议(protocol)。
如果您尝试发送 RSET 动词(例如,在调用 email()
之前调用 $mail->getSMTPInstance()->reset();
),发送第二封邮件时的错误更清楚:
2014-11-04 00:23:18 SMTP ERROR: RSET command failed:
2014-11-04 00:23:18 SMTP NOTICE: EOF caught while checking if connected
我不是加密专家,所以我无法深入了解。但我很确定 stream_socket_client 使用的资源(并用 stream_socket_enable_crypto 包装)存储执行下一个 TLS 事务所需的一些上下文信息。在第一个 child 发送电子邮件后,资源的上下文在 child 的内存中是最新的,但在 parent 的内存中不是。因此,当您尝试使用旧上下文发送另一封电子邮件时,TLS 会中断。
关于php - 防止在父级中打开的流套接字被子叉关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26612780/