本地 IPC、POSIX 消息队列 (mqueues) 或 Unix 域(本地)套接字哪个更好?

发布于 2024-09-24 09:45:45 字数 622 浏览 0 评论 0原文

使用 POSIX 消息队列或 Unix 域套接字进行本地 IPC 通信哪个更好?

我曾在机器(不是域)之间使用 Unix 套接字,我记得建立和断开连接会导致套接字在最终消失之前停留一段时间。此外,如果您想要“可靠”的交换,则必须使用 TCP 或设计应用程序以返回 ACK。我不确定这是否也适用于 Unix 域套接字。

在我当前的项目中,我们需要本地IPC。我的第一反应是使用 POSIX MQueue,因为我之前曾使用它们进行本地消息传递。然而,一位同事建议使用 Unix 域套接字。

是一个比另一个更好,还是编程熟悉程度的问题?或者也许它取决于正在创建的应用程序?

从总体上看,我们正在开发的应用程序遵循客户端/服务器模型。客户端向服务器发送消息以“做某事”。然而,客户端不会等待“已完成”响应——尽管他们确实想知道他们的请求是否已收到。

发送端的基本逻辑是:

connect to server
send request
note if the send worked or not
disconnect from server

一台服务器可以有数百个客户端。

我们正在运行 Linux 操作系统的 SMP 系统(4-8 核)上执行。

提前致谢。

Is it better to use POSIX message queues or Unix domain sockets for local IPC communication?

I have worked with Unix sockets between machines (not domain) and I remember that making and breaking the connection would cause sockets to linger awhile before they finally went away. Moreover, if you wanted a "reliable" exchange you either had to use TCP or design the application to return an ACK. I'm not certain if this also applies to Unix domain sockets though.

In my current project we need local IPC. My first reaction was to use POSIX MQueues, since I've used them before for local messaging. However, a co-worker is suggesting Unix domain sockets instead.

Is one better than the other, or is it a matter of programming familiarity? Or perhaps its depends upon the application being created?

At a big picture the application we are working on follows a client/server model. The clients send messages to the server to "do something". However, the client doesn't wait for an "its done" response -- although they do want to know if their request has been received or not.

The basic logic for the send side is:

connect to server
send request
note if the send worked or not
disconnect from server

There can be hundreds of clients to the one server.

We're are executing on an SMP system (4-8 cores) running the Linux OS.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

晚风撩人 2024-10-01 09:45:45

UNIX 域套接字不必“徘徊”在类似 TIME_WAIT 的状态,因为该等待时间用于防止来自连接的杂散数据包仍在 Internet 上徘徊。这种担忧并不适用于本地。

UNIX 域套接字可以是 SOCK_STREAM(如 TCP)或 SOCK_DGRAM(如 UDP),并额外保证 UNIX 域数据报套接字是可靠的且不会重新排序数据报。

如果您想确定您的其他应用程序已读取您发送的消息,您仍然需要某种类型的 ACK(即使使用 TCP);毕竟,即使 send() 成功,它也可能在有机会处理消息之前就崩溃了。 (这也适用于消息队列 - 为了完全确保消息不会丢失,接收应用程序必须将请求写入日志,将其刷新到磁盘,然后发回确认)。

我同意选择本质上是编程熟悉程度的问题。

UNIX domain sockets do not have to "linger" in a TIME_WAIT-like status, since that wait time is used in case there are stray packets from the connection still wandering around the Internet. The concern doesn't apply locally.

UNIX domain sockets can be either SOCK_STREAM (like TCP) or SOCK_DGRAM (like UDP), with the added guarantee that UNIX domain datagram sockets are reliable and don't re-order datagrams.

You will still need some kind of ACK (you do even with TCP) if you want to be certain that your other application has read the message you sent; after all, even if the send() succeeded it may have crashed before it had a chance to process the message. (This applies to message queues too - to be totally sure that a message won't be lost, the recieving application must write the request to a journal, flush that to disk and then send back an acknowledgement).

I agree that the choice is essentially a matter of programming familiarity.

且行且努力 2024-10-01 09:45:45

是一个比另一个更好,还是编程熟悉程度的问题?或者也许它取决于正在创建的应用程序?

SysV 消息队列与 UNIX 域数据报套接字相比有以下主要区别:

  • 您可以使用 poll() 套接字,但不能使用消息队列。

  • 消息队列是全局的,可能(通常确实)需要一些管理参与:清理旧的挂起的 SysV 资源是许多系统管理员的日常例行工作之一。虽然 UNIX 域的语义要简单得多,并且应用程序通常可以在内部完全维护它,而无需系统管理员的参与。

  • (?) 消息队列是持久的,它可能保留来自旧会话的消息。 (记不清了,但 IIRC 这在我身上发生过不止一次)。

  • 查看man msgrcv,我没有看到套接字的MSG_PEEK的类似物。很少需要,但有时非常方便。

  • 大多数时候,用户更喜欢在配置中使用符号名称,而不是数字键 ID。缺乏符号键 IMO 是对 SysV 界面设计者的严重疏忽。

与所有 SysV 资源一样,它们的管理是主要的 PITA。如果您让系统决定消息队列 ID,那么您必须注意与其他应用程序正确共享它。 (而且您还必须以某种方式告诉管理员该 ID 最终必须被删除)。如果您允许为消息队列配置密钥,那么您可能会遇到一些小问题,即该 id 已被某些应用程序使用或者它是先前运行的残余。 (看到服务器仅因为耗尽 SysV 资源而重新启动是很常见的。)

总而言之,我会尽可能避免使用 SysV 资源:在大多数常见情况下,缺乏 poll() 支持是一个大问题。

但是,客户端不会等待“已完成”响应 - 尽管他们确实想知道他们的请求是否已收到。

这是事务处理的常见困境。一般响应是(如在 RDBMS 中)您不能,并且在通信中断(崩溃或其他原因)后,应用程序必须检查自身是否已处理请求。

由此我可以看出 TCP 可能是更好的选择。仅当客户端收到服务器的肯定响应时,客户端才会发送请求并声明请求已完成。服务器除非能够向客户端发送响应,否则必须回滚事务。

Is one better than the other, or is it a matter of programming familiarity? Or perhaps its depends upon the application being created?

SysV message queues compared to UNIX domain datagram sockets have the major differences I'm aware of:

  • You can poll() socket, but you can't message queue.

  • Message queue is global and might (and usually do) require some administrative involvement: cleaning old hanging SysV resources is one of the many sysadmin daily routines. While semantics of UNIX domain is much simpler and applications can generally maintain it completely internally without sysadmin involvement.

  • (?) Message queue is persistent, it might retain messages from the old sessions. (Can't recall that bit precisely, but IIRC that was happening to me more than once).

  • Looking at the man msgrcv I do not see analogue of socket's MSG_PEEK. Rarely needed, but at times comes quite handy.

  • Most of the time, users prefer to use in the configuration symbolic names, not the numeric key id. Lack of symbolic keys IMO is quite grave oversight on part of the SysV interface designers.

As with all SysV resources, their management is the major PITA. If you let system decide message queue ID, then you have to take care of properly sharing it with other applications. (And you also has to tell admins somehow that the ID has to be removed eventually). If you allow to configure the key for message queue, then you might run into trivial problems that the id is already used by some application or it is a remnant of the previous run. (Seeing servers being reboot only because they run out of SysV resources is pretty common.)

All in all, I avoid SysV resources when possible: lack of poll() support under most common circumstances is a deal breaker.

However, the client doesn't wait for an "its done" response -- although they do want to know if their request has been received or not.

That is a common dilemma of transactional processing. General response is (as in RDBMSs) you can't and after communication interruption (crash or whatever) the application has to check itself whether the request was already processed or not.

From that I can tell that probably TCP would be a better choice. Client sends request and declares it as finished only when it gets positive response from the server. Server unless it is capable of sending the response to client, has to rollback the transaction.

初雪 2024-10-01 09:45:45

我建议您考虑使用 DBus 来实现这样的应用程序,即使只是为了它们的数据编组和类似 RPC 的接口(同步和异步)。它本身使用域套接字,并且在初始学习曲线之后工作得非常好。

I'd suggest looking at DBus for such an application, if only for their data marshalling and RPC like interface (both synchronous and asynchronous). It uses domain sockets natively and works really welll after an initial learning curve.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文