阻塞通道 vs 异步消息传递

10
我注意到了两种“消息传递”方法,一种是Erlang使用的,另一种是Stackless Python使用的。据我所知,它们的区别如下:
Erlang 的方式 - 消息被发送并排队到接收进程的邮箱中。然后,它们按照先进先出(FIFO)的顺序被移除。一旦第一个进程发送了消息,它就可以继续执行。
Python 的方式 - 进程 A 排队等待向进程 B 发送消息。B 正在执行其他操作,因此 A 被冻结,直到 B 准备好接收消息。一旦 B 打开了读通道,A 发送数据,然后两者都继续执行。
现在,我认为 Erlang 的优点在于它没有任何被阻塞的进程。如果 B 从未能够接收,则 A 仍然可以继续执行。然而,我注意到在我编写的一些程序中,由于消息流入大于流出,Erlang 的消息盒可能会充满数百个(或数千个)消息。
现在,我还没有在任何一个框架/语言中编写过大型程序,所以我想知道你们对此的经验,以及这是否是我应该担心的事情。
是的,我知道这是抽象的,但我也在寻找相对抽象的答案。
2个回答

8
我的 Erlang 编程经验告诉我,当您期望高消息传输率(也就是生产者比消费者更快)时,您需要添加自己的流量控制。一个简单的场景:
  • 消费者将发送消息,等待确认,然后重复执行。
  • 生产者将等待消息,收到并处理消息后发送确认,然后重复执行。
您还可以反过来,生产者等待消费者来获取下一个可用的 N 条消息。
这些方法和其他流量控制可以隐藏在函数后面,第一个方法在 gen_server:call/2,3 中已经存在于 gen_server OTP 行为进程中。
在 Erlang 中,我认为异步消息传递是更好的方法,因为当延迟很高时,您可能非常想避免计算机之间的同步。您可以组合聪明的方法来实现流量控制。例如,要求消费者针对生产者发送的每 N 条消息发送确认,或者定期发送特殊的“在收到此消息后请回复我”消息以计算 ping 时间。

4
大体上来说,这是无限队列和有限队列之间的区别。无栈通道可以被视为大小为0的队列的特例。
有限队列容易死锁。两个线程/进程试图互相发送消息,但是它们的队列都已满。
无限队列具有更微妙的失败。可能出现大型邮箱无法满足延迟要求的情况,就像你提到的一样。继续走下去,它最终会溢出;没有无限的内存可用,所以它实际上只是一个具有巨大限制并在满时中止进程的有限队列。
哪种更好?这很难说。这里没有简单的答案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接