分布式系统上的邮箱处理器
我在 Expert F# 第 379 页的副本中注意到以下评论:
传递和处理消息
经常区分 共享内存并发和消息 传递并发。 前者是 在本地机器上通常效率更高 并在“使用 共享内存并发”稍后 这一章。 后者扩展到 没有共享的系统 例如,分布式内存 系统,也可用于避免 相关的性能问题 共享内存。
我对没有共享内存的进程之间的消息传递并发性感兴趣。 Expert F# 和互联网上演示如何使用 MailboxProcessor 的所有示例都包含此代码的一些变体:
let counter =
MailboxProcessor.Start(fun inbox ->
let rec loop n =
async {
do printfn "n = %d, waiting... " n
let! msg = inbox.Receive()
match msg with
| -1 ->
do printfn "'Til the bitter end..."
return ()
| n -> return! loop(n + msg)
}
loop 0)
counter.Post(20)
counter.Post(50)
counter.Post(-1) // kill mailbox
换句话说,您必须在共享内存中拥有 MailboxProcessor 的句柄,然后才能将消息发布到其通道。 据我所知,这不是 Erlang 风格的并发,因为您只能在同一进程中将消息发送到 MailboxProcessors(注意:进程,而不是线程)。
一个进程中的一个 MailboxProcessor 是否可以将消息发送到另一个 MailboxProcessor 进程? 如果是的话,您能提供一个样本吗?
I noticed the following comment in my copy of Expert F# on page 379:
Passing and Processing Messages
A distinction is often made between
shared-memory concurrency and message
passing concurrency. The former is
often more efficient on local machines
and is covered in the section "Using
Shared-Memory Concurrency" later in
this chapter. The latter scales to
systems where there is no shared
memory, for example, distributed
systems, and can also be used to avoid
performance problems associated with
shared memory.
I'm interested message passing concurrency between processes with no shared memory. All of the examples in Expert F# and on the internet which demonstrate how to use the MailboxProcessor contain some variation of this code:
let counter =
MailboxProcessor.Start(fun inbox ->
let rec loop n =
async {
do printfn "n = %d, waiting... " n
let! msg = inbox.Receive()
match msg with
| -1 ->
do printfn "'Til the bitter end..."
return ()
| n -> return! loop(n + msg)
}
loop 0)
counter.Post(20)
counter.Post(50)
counter.Post(-1) // kill mailbox
In other words, you have to have a handle on your MailboxProcessor in shared-memory before you can post messages to its channel. This isn't Erlang-style concurrency as far as I know it, since you can only post messages to MailboxProcessors in the same process (note: process, not thread).
Is it possible for one MailboxProcessor in one process to send messages to another MailboxProcessor process? If so, could you provide a sample?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
MailboxProcessor 和 AsyncReplyChannel 不提供与 Erlang 中的“pid bang”(Pid!)操作相同的位置透明度。 当然,这只有在正确配置分布式 Erlang 节点(即名称、DNS、同步模块、cookie 等)时才有效。OTP 中有一些功能可以使管理变得更容易。 当然,如果 Erlang 进程位于同一节点上,它就可以工作。 但是,分布式 Erlang 存在一些问题。
“网络是安全的。”
内置的分布式 Erlang 机制假设网络是安全的。 因此,当需要安全性时,会采用基于套接字的代理 Erlang 进程通信方法。
“网络可靠。”
分布式 Erlang 的工作原理之一是它的错误处理理念,即进程不可靠,因此只能通过进程监视器通信来实现容错。 OTP 编码模式(即 Supervisor)来实现这一理念。 Erlang 中的可靠消息传递可以通过 Mnesia(分布式数据库)实现,就像在 RabbitMQ 中所做的那样,但您不能将其开箱即用。
最后,分布式通信从未如此简单。 我们可以在 F# 中实现一个 AsynchWorker 来充当我们的代理并通过 AsynchReplyChannel.Send 与其进行通信。 我们仍然要思考分布式计算的谬误。
最后,消息传递风格的并发并不意味着进程外通信。 它确实意味着没有需要用锁来管理的共享状态,因此是一个更简单、更不易出错的并行计算模型。 我认为这个素数筛是这种并发风格的一个很好的例子。 F# 示例不像 Squeak 或 Erlang 实现那样美观,因为缺乏用于消息传递的内置语法,但它可以工作。
The MailboxProcessor and AsyncReplyChannel do not provide the same location transparency as the "pid bang" (Pid !) operation in Erlang. Of course, this only works when the distributed Erlang nodes are configured properly, i.e. names, DNS, synchronized modules, cookies, etc. There are some features in OTP to make this administration easier. Of course, if the Erlang processes are on the same node, it just works. But, there are some wrinkles with distributed Erlang.
"The network is secure."
The built-in distributed Erlang mechanisms assume the network is secure. So, a socket-based communication approach with proxy Erlang processes is employed when security is necessary.
"The network is reliable."
One of the things that make distributed Erlang work is its philosophy of error handling, namely that processes are unreliable and thus fault tolerance is only achieved by communicating process monitors. OTP codifies patterns (i.e. Supervisor) to implement this philosophy. Reliable messaging in Erlang can be achieved via Mnesia (a distributed database), as was done in RabbitMQ, but you don't get it out of the box.
In the end, distributed communications are never so easy. We could implement an AsynchWorker in F# to act as our proxy and communicate with it via AsynchReplyChannel.Send. We still have to think about the fallacies of distributed computing.
Finally, message passing style concurrency does not imply out-of-process communication. It does imply that there is no shared state to manage with locks, thus a simpler, less error prone model of parallel computation. I think this Prime Number Sieve is a great example of this style of concurrency. The F# example is not as aesthetically pleasing as the Squeak or an Erlang implementation, because of the lack of built-in syntax for message passing, but it works.
我认为您对术语有点困惑。 Erlang 进程不一定直接对应于操作系统进程。 一个给定的操作系统进程可以有多个 Erlang 进程(通常都是这样),就像你的进程有多个线程一样。 如果您想在多个操作系统进程之间进行通信,您可能需要查看 System.Runtime.Remoting.Channels.Ipc。 可以想象,可以围绕这些 API 创建 MailboxProcessor 风格的包装器。
I think you've been a little confused by terminology. Erlang processes do not necessarily correspond directly to OS processes. A given OS process can have multiple Erlang processes (and usually does), much like your process has multiple threads. If you want to communicate between multiple OS processes, you may want to check out System.Runtime.Remoting.Channels.Ipc. Conceivably a MailboxProcessor-style wrapper could be created around these APIs.
也许这会
使用 F# 代理进行 MapReduce
我没有收到太多反馈,所以没有确保它100%正确。 如果您认为它不好,请告诉我。
感谢!
Perhaps this will do
Map Reduce with F# agents
I haven't gotten much feedback so no sure its 100% correct. If you think its bad please letme know .
Thank!