【问题标题】:Are message queues obsolete in linux?消息队列在 linux 中过时了吗?
【发布时间】:2010-11-01 07:50:16
【问题描述】:

我最近一直在 Linux 中使用消息队列(System V,但 POSIX 也应该没问题),它们似乎非常适合我的应用程序,但是在阅读了 The Art of Unix Programming 我不确定它们是否真的不错的选择。

http://www.faqs.org/docs/artu/ch07s02.html#id2922148

System V IPC 的上层消息传递层已基本停止使用。下层由共享内存和信号量组成,在需要进行互斥锁定和在同一台机器上运行的进程之间进行一些全局数据共享的情况下,仍然有重要的应用。这些 System V 共享内存设施演变成 POSIX 共享内存 API,支持 Linux、BSD、MacOS X 和 Windows,但不支持经典的 MacOS。

http://www.faqs.org/docs/artu/ch07s03.html#id2923376

System V IPC 工具存在于 Linux 和其他现代 Unix 中。但是,由于它们是遗留功能,因此它们并不经常使用。到 2003 年中期,Linux 版本仍然存在缺陷。似乎没有人关心修复它们。

System V 消息队列在较新的 Linux 版本中是否仍然存在错误?不知道作者的意思是不是POSIX消息队列应该没问题?

似乎套接字是几乎所有东西的首选 IPC(?),但我看不出用套接字或其他东西实现消息队列是多么简单。还是我想的太复杂了?

我不知道我使用嵌入式 Linux 是否相关?

【问题讨论】:

    标签: linux sockets posix ipc message-queue


    【解决方案1】:

    我实际上并没有使用过 POSIX 消息队列,因为我总是希望保留在网络上分发消息的选项。考虑到这一点,您可能会考虑一个更强大的消息传递接口,例如 zeromq 或实现 AMQP 的东西。

    0mq 的优点之一是,当在多线程应用程序的同一进程空间中使用时,它使用了非常快的无锁零拷贝机制。不过,您也可以使用相同的接口通过网络传递消息。

    【讨论】:

      【解决方案2】:

      就我个人而言,我非常喜欢消息队列,并且认为它们可以说是 unix 世界中使用率最低的 IPC。它们快速且易于使用。

      一些想法:

      • 其中一些只是时尚。旧的东西又变成了新的。在消息队列上添加一个闪亮的老爸,它们可能是明年最新和最热门的东西。看看 Google 的 Chrome 使用单独的进程而不是其选项卡的线程。突然间,人们很兴奋,当一个标签被锁定时,它并没有关闭整个浏览器。

      • 共享内存有点像人类的光环。如果您没有从机器中挤出最后一个循环,那么您就不是“真正的”程序员,并且 MQ 的效率略低。对于许多(如果不是大多数)应用程序来说,这完全是无稽之谈,但有时一旦形成一种思维定势就很难打破。

      • MQ 确实不适合具有无限数据的应用程序。管道或套接字等面向流的机制更易于使用。

      • System V 变体确实已经失宠。一般来说,尽可能使用 POSIX 版本的 IPC。

      【讨论】:

      • 7 年后.. 希望它仍然有点相关不会太多:我想知道Ubuntu 14.04linux 3.13 上的消息队列的默认设置,即cat /proc/sys/fs/mqueue/msg_max 列出 10(消息在队列中)和/proc/sys/fs/mqueue/msgsize_max 是 8192(字节)——它们非常小。这些默认值是否有一些严格的原因,或者它们只是旧的? (man mq_overview 说 msg_max 的硬限制大约是 32768,这是相当高的。)我并不是要创建一个无限流式队列,而是 msg_max 中的 100-1000 好吗?
      • 有点晚了,但是:当我使用 POSIX 队列时,队列中有 5-100 条消息,并且没有遇到问题@xealits
      【解决方案3】:

      是的,我认为消息队列适用于某些应用程序。 POSIX 消息队列提供了一个更好的界面,特别是,您可以给队列名称而不是 ID,这对于故障诊断非常有用(更容易看出哪个是哪个)。

      Linux 允许您将 posix 消息队列挂载为文件系统并使用“ls”查看它们,使用“rm”删除它们也非常方便(系统 V 依赖于笨重的“ipcs”和“ipcrm”命令)

      【讨论】:

      • 此功能也可用于 UNIX 数据报套接字。我可以将数据报套接字绑定到文件并以与 POSIX 消息队列相同的方式接收。我什至可以使用netcat 将测试数据发送到数据报套接字文件。
      【解决方案4】:

      POSIX 消息队列的最大缺点:

      • POSIX 消息队列不使其成为与select() 兼容的要求。(它适用于Linux 中的select(),但不适用于Qnx 系统)
      • 它有惊喜。

      Unix 数据报套接字执行与 POSIX 消息队列相同的任务。而 Unix 数据报套接字工作在套接字层。它可以与select()/poll() 或其他IO-wait 方法一起使用。在设计基于事件的系统时,使用select()/poll() 具有优势。这样可以避免忙循环。

      消息队列中有惊喜。想想mq_notify()。它用于获取接收事件。听起来我们可以通知一些关于消息队列的事情。但它实际上是注册通知而不是通知任何东西。

      关于mq_notify() 的更多惊喜是它必须在每个mq_receive() 之后调用,这可能会导致竞争条件(当在mq_receive() 和@987654332 的调用之间的一些其他进程/线程调用mq_send() 时@)。

      并且它有一整套mq_open, mq_send(), mq_receive() and mq_close() 有自己的定义,这是多余的,在某些情况下与套接字open(),send(),recv() and close() 方法规范不一致。

      我不认为消息队列应该用于同步。 eventfdsignalfd 很适合。

      它(POSIX 消息队列)有一些实时支持。它具有优先功能。

      Messages are placed on the queue in decreasing order of priority, with newer messages of the same priority being placed after older messages with the same priority.
      

      但这个优先级也可用于套接字作为带外数据!

      最后,对我来说,POSIX 消息队列是一个遗留 API。只要不需要实时功能,我总是更喜欢 Unix 数据报套接字而不是 POSIX 消息队列。

      【讨论】:

        【解决方案5】:

        消息队列对于构建本地解耦应用程序非常有用。它们超级快,它们是块组织的(不需要缓冲,切割等,这是蒸汽套接字的情况),基本上很少的 memcpy() 操作(用户代码复制块到内核,内核复制块到其他进程读取q),这就是消息传递的故事。一些行业知名的中间件,例如 Oracle Tuxedo 或 Mavimax Enduro/X 使用这些队列来帮助构建负载平衡、高性能、容错的分解分布式应用程序。这些队列允许进行负载平衡,当多个可执行文件从同一个队列中读取时,内核调度程序只是将消息分发给曾经处于空闲状态的进程。 Linux 的好处是轮询可以在 Posix 队列上完成,这有助于解决某些场景。对于 IBM AIX,可以对 System V 队列进行轮询。

        例如,两个进程可以通过队列轻松地进行本地通信,并提供令人印象深刻的吞吐量(~70k req+rply/sec):

        如果需要联网,例如 Enduro/X 提供 tpbridge 进程,该进程基本上从本地队列中读取消息,将块发送到其他机器,另一端将消息注入本地队列。

        此外,与套接字相比,队列不会出现任何问题,例如当某些二进制文件崩溃时,例如繁忙/延迟的套接字,即启动时的程序可以立即开始读取队列并进行处理。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-03-17
          • 2014-08-26
          • 1970-01-01
          • 2013-04-02
          • 2018-01-20
          • 2011-05-14
          • 2018-01-16
          • 2011-09-18
          相关资源
          最近更新 更多