内容简介:Go vs Erlang
源于从Erlang到 Go 的一些思维碰撞,就像当初从C++到Erlang一样,整理下来记于此。
Actor
Actor模型,又叫参与者模型,其”一切皆参与者(actor)”的理念与面向对象编程的“一切皆是对象”类似,但是面向对象编程中对象的交互通常是顺序执行的(占用的是调用方的时间片,是否并发由调用方决定),而Actor模型中actor的交互是并行执行的(不占用调用方的时间片,是否并发由自己决定)。
在Actor模型中,actor执行体是第一类对象,每个actor都有自己的ID(类比人的身份证),可以被传递。actor的交互通过发送消息来完成,每个actor都有一个通信信箱(mailbox,本质上是FIFO消息队列),用于保存已经收到但尚未被处理的消息。actorA要向actorB发消息,只需持有actorB ID,发送的消息将被立即Push到actorB的消息信箱尾部,然后返回。因此Actor的通信原语是异步的。
从actor自身来说,它的行为模式可简化为:
- 发送消息给其它的actor
- 接收并处理消息,更新自己的状态
- 创建其它的actor
一个好的Actor模型实现的设计目标:
- 调度器: 实现actor的公平调度
- 容错性: 具备良好的容错性和完善错误处理机制
- 扩展性: 屏蔽actor通信细节,统一本地actor和远程actor的通信方式,进而提供分布式支持
- 热更新? (还没弄清楚热更新和Actor模型,函数式范式的关联性)
在Actor模型上,Erlang已经耕耘三十余载,以上提到的各个方面都有非常出色的表现,其OTP整合了在Actor模型上的最佳实践,是Actor模型的标杆。
CSP
顺序通信进程(Communicating sequential processes,CSP)和Actor模型一样,都由独立的,并发的执行实体(process)构成,执行实体间通过消息进行通信。但CSP模型并不关注实体本身,而关注发送消息使用的通道(channel),在CSP中,channel是第一类对象,process只管向channel写入或读取消息,并不知道也不关心channel的另一端是谁在处理。channel和process是解耦的,可以单独创建和读写,一个process可以读写(订阅)个channel,同样一个channel也可被多个process读写(订阅)。
对每个process来说:
- 从命名channel取出并处理消息
- 向命名channel写入消息
- 创建新的process
Go语言并没有完全实现CSP理论(参见 知乎讨论 ),只提取了CSP的process和channel的概念为并发提供理论支持。目前Go已经是CSP的代表性语言。
CSP vs Actor
- 相同的宗旨:”不要通过共享内存来通信,而应该通过通信来共享内存”
- 两者都有独立的,并发执行的通信实体
- Actor第一类对象为执行实体(actor),CSP第一类对象为通信介质(channel)
- Actor中实体和通信介质是紧耦合的,一个Actor持有一个Mailbox,而CSP中process和channel是解耦的,没有从属关系。从这一层来说,CSP更加灵活,如可以处理不同channel消息的优先级
- Actor模型中actor是主体,mailbox是匿名的,CSP模型中channel是主体,process是匿名的。从这一层来说,由于Actor不关心通信介质,因此在分布式和容错方式更有优势
Go vs Erlang
- CSP vs Actor并发范式的种种关联与区别
- 均实现了语言级的coroutine,在阻塞时能自动让出调度资源,在可执行时重新接受调度
- erlang/otp在actor上扩展了分布式支持,热更和高容错,这些都是go欠缺的
- go的channel是有容量限制的,因此只能一定程度地异步,erlang的mailbox是无限制的,是纯粹的异步语义,但也带来的消息队列膨胀的危险
Actor in Go
在用Go写GS框架时,不自觉地会将goroutine封装为actor来使用:
- GS的执行实体(如玩家,公会)的逻辑具备强状态和功能聚合性,不易拆分,因此通常是一个实体一个goroutine
- 实体接收的逻辑消息具备弱优先级,高顺序性的特点,因此通常实体只会暴露一个Channel与其它实体交互(结合go的interface{}很容易统一channel类型),这个channel称为RPC channel,它就像这个goroutine的ID,几乎所有逻辑goroutine之间通过它进行交互
- 除此之外,实体还有一些特殊的channel,如定时器,外部命令等。实体goroutine对这些channel执行select操作,读出消息进行处理
- 加上goroutine的状态数据之后,此时的goroutine的行为与actor相似:接收消息(多个消息源),处理消息,更新状态数据,向其它goroutine发送消息(通过RPC channel)
到目前为止,goroutine和channel解耦的优势并未体现出来,我认为主要的原因仍然是GS执行实体的强状态性和对异步交互流程的顺序性导致的。
在研究这个问题的过程中,发现已经有人已经用go实现了支持分布式的Actor模型: https://github.com/AsynkronIT/protoactor-go。 真是有种他山逢知音的感觉。:)
参考:
以上所述就是小编给大家介绍的《Go vs Erlang》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
区块链革命
[加]唐塔普斯科特(Don Tapscott)、[加]亚力克斯·塔普斯科特(Alex Tapscott) / 中信出版集团股份有限公司 / 2016-9 / 69
(1)国际大腕“数字经济之父”继畅销书《维基经济学》之后再出力作! (2)一本真正全景式描述区块链理论及应用的巨著! (3)苹果共同创始人史蒂夫·沃兹尼亚克、世界经济论坛创始人和论坛主席克劳斯·施瓦布、网景及硅谷安德森·霍洛维茨风险投资公司创始人马克·安德森、麦肯锡董事长兼全球总裁鲍达民、 百事公司首席执行官卢英德、丹·舒尔曼 Paypal公司首席执行官等全球政治界、学术界和商界精英联......一起来看看 《区块链革命》 这本书的介绍吧!