分布式系统上的邮箱处理器

时间:2009-02-01 21:55:51

标签: concurrency f# erlang

我在第379页的专家F#副本中注意到以下注释:

  

传递和处理讯息

     

经常区分   共享内存并发消息   传递并发。前者是   通常在本地机器上更有效率   并在“使用”一节中介绍   共享内存并发“稍后   本章。后者扩展到   没有共享的系统   内存,例如,分布式的   系统,也可以用来避免   与...相关的性能问题   共享内存。

我对在没有共享内存的进程之间传递并发的消息感兴趣。 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

换句话说,您必须在共享内存中拥有邮箱处理器的句柄,然后才能将邮件发布到其频道。据我所知,这不是Erlang风格的并发,因为你只能在同一个进程中将消息发布到MailboxProcessors(注意:进程,而不是线程)。

一个进程中的一个MailboxProcessor是否可以将邮件发送到另一个MailboxProcessor进程?如果是这样,你能提供样品吗?

3 个答案:

答案 0 :(得分:8)

我觉得你对术语感到有些困惑。 Erlang进程不一定直接对应于OS进程。给定的OS进程可以有多个Erlang进程(通常也有),就像你的进程有多个线程一样。如果要在多个OS进程之间进行通信,可能需要查看System.Runtime.Remoting.Channels.Ipc。可以想象,可以围绕这些API创建一个MailboxProcessor风格的包装器。

答案 1 :(得分:8)

MailboxProcessor和AsyncReplyChannel不提供与Erlang中的“pid bang”(Pid!)操作相同的位置透明度。当然,这仅适用于正确配置分布式Erlang节点的情况,即名称,DNS,同步模块,cookie等.OTP中有一些功能可以使管理更容易。当然,如果Erlang进程在同一节点上,它就可以正常工作。但是,分布式Erlang存在一些皱纹。

“网络安全。” 内置的分布式Erlang机制假设网络是安全的。因此,当需要安全性时,采用基于套接字的通信方法和代理Erlang进程。

“网络可靠。” 使分布式Erlang工作的一个原因是它的错误处理理念,即进程不可靠,因此只有通信流程监视器才能实现容错。 OTP编纂模式(即主管)以实现这一理念。 Erlang中的可靠消息传递可以通过Mnesia(一个分布式数据库)实现,就像在RabbitMQ中所做的那样,但是你没有开箱即用。

最后,分布式通信从未如此简单。我们可以在F#中实现AsynchWorker作为我们的代理,并通过AsynchReplyChannel.Send与它进行通信。我们仍然需要考虑分布式计算的谬误。

最后,消息传递样式并发并不意味着进程外通信。它确实意味着没有用锁管理的共享状态,因此是一种更简单,不易出错的并行计算模型。我认为这个Prime Number Sieve是这种并发风格的一个很好的例子。 F#示例不像Squeak或Erlang实现那样美观,因为缺少内置的消息传递语法,但它可以工作。

答案 2 :(得分:1)

也许这样做

Map Reduce with F# agents

我没有得到太多反馈,所以不确定它的100%是否正确。如果你认为它很糟糕,请告诉我们。

感谢!