在 PHP 中使用 msg_send() 导致错误 11...找不到解决方案

Using msg_send() in PHP results in error 11... Cannot find a solution

我目前正在构建一个使用 PHP 内置消息队列的小型应用程序。 我有 1 个“服务器”进程和 1 个“客户端”进程。消息从服务器流向客户端。

它们是简单的 JSON 对象,先序列化,然后发送。

使用此代码

<?php
$send = msg_send($q, MESSAGE_TYPE_EXECUTION, $update, true, false, $error);

if (isset($error) && $error != 0) {
    echo 'Execution error: ' . $error . PHP_EOL;
}

// $q is the message queue integer
// MESSAGE_TYPE_EXECUTION is integer 1
// $update is the JSON string
// true is that the JSON string is serialised
// false is that it is blocking (which it is not)
// $error get's filled when an error occurs (see below)

这没有问题,直到它没有。 有时几分钟后,有时几小时后出现以下错误:

PHP Warning:  msg_send(): msgsnd failed: Resource temporarily unavailable in 
/var/www/server.php on line 57

$error变量的值为整数11。 此错误之后的所有消息都将出现错误 11,直到我重新启动该过程并且一切都再次工作(一段时间,直到再次出现相同的错误)

我一直在搜索但找不到任何解释错误 11 是什么,如何在不重新启动进程的情况下管理和修复它。

欢迎提供任何线索、信息、示例等。我真的希望 server.php 可靠。

-- 编辑 -- client.php 是获取消息的过程(它们或多或少相同,但具有其他值)

它使用这个从队列中获取消息(填写server.php)

<?php
$update = msg_receive($q, 0, $messagetype, 1024, $message, true, MSG_IPC_NOWAIT && MSG_NOERROR, $error);

if ($update) {
    // Do stuff
}
usleep(1000000);

我还没有检查内存使用情况,会调查一下

使用的平台

所以,在一些信息和线索之后找到了解决方案(阅读对我原来问题的评论),由@ChrisHaas 提出(再次感谢!)。经过一些修补后,现在 运行 一切顺利,msg_send() 没有错误 11。

PHP msg_send() 调用基本上是 msgsnd 的包装 所以在那里可以找到很多信息,还有关于你可能遇到的错误(结合使用 msg_receive() 阅读消息时使用的标志)

队列的总大小和它可以容纳的消息总数是有限的(但是,我还没有找到增加队列总大小的方法)。

我收到错误 11 的原因有以下几点:

  • 我创建的客户端从队列中获取消息的速度太慢,导致它 运行 达到最大限制并崩溃。除了重新启动所有涉及的进程之外,我没有找到解决这种情况的解决方案。一遍又一遍地重复同样的事情。
  • 我还在 msg_receive() 中增加了阅读消息的大小,因为有时消息很大(大多数很小)。但是当你声明一个太小的尺寸时,大消息将保留在队列中并阻塞它直到它崩溃。增加 max_size 也有助于获取更大的消息。

长话短说:在我看来,错误 11 与完整的消息队列有关(尽管我仍然没有 100% 明确的记录答案)。

解决问题的提示:

  • 确保获取所有大邮件。
  • 确保读出的速度至少与发送队列中的消息一样快。
  • 在终端中使用命令 ipcs -q 检查您的队列。它允许您查看当前活动的队列。密切关注它可以让您看到它慢慢地解决问题。

希望 php.net 上的文档在这种情况下更好...