好莱坞是一种超快的演员发动机,用于速度和低延迟应用。考虑游戏服务器,广告经纪人,交易引擎等...它可以在1秒内处理1000万条消息。
Actor模型是用于构建高度并发和分布式系统的计算模型。卡尔·休伊特(Carl Hewitt)在1973年引入了它,是一种以更可扩展和容忍性的方式处理复杂系统的方式。
在演员模型中,基本的构建块是一个演员,有时被称为好莱坞的接收器,这是一个独立的计算单位,通过交换消息与其他参与者进行通信。每个演员都有自己的状态和行为,只能通过发送消息与其他参与者进行交流。这种消息范围的范式允许高度分散且容忍故障的系统,因为即使其他参与者失败或不可用,演员也可以继续独立运作。
演员可以组织成等级制度,高级演员在监督和协调下层演员。这允许创建可以以优雅和可预测的方式处理故障和错误的复杂系统。
通过在您的应用程序中使用Actor模型,您可以构建高度可扩展且容易耐受的系统,这些系统可以处理大量并发用户和复杂的交互。
在演员失败(缓冲机制)上保证消息传递
火与忘记或要求和响应消息,或两者兼而有之
高性能DRPC作为运输层
不反射的优化原始缓冲液
轻巧且高度可定制
集群支持编写分布式自我发现的演员
make bench
spawned 10 engines spawned 2000 actors per engine Send storm starting, will send for 10s using 20 workers Messages sent per second 3244217 .. Messages sent per second 3387478 Concurrent senders: 20 messages sent 35116641, messages received 35116641 - duration: 10s messages per second: 3511664 deadletters: 0
go get github.com/anthdm/hollywood/...
好莱坞需要Golang版本
1.21
我们建议您首先写一些本地运行的示例。由于编译器能够找出所使用的类型,因此本地运行更简单。远程运行时,您需要为编译器提供原始的定义。
让我们浏览一个Hello World信息。完整的示例可在Hello World文件夹中找到。让我们从主要开始:
引擎,err:= Actor.newEngine(Actor.newengineconfig())
这会创建一个新的引擎。引擎是好莱坞的核心。它负责产卵,发送消息和处理演员的生命周期。如果好莱坞未能创建引擎,它将返回错误。对于开发,您不应该将任何选项传递给发动机,以便您可以通过零。我们稍后再查看选项。
接下来,我们需要创建一个演员。这些接口必须实现之后,这些次数被称为Receivers
。让我们创建一个新演员,该演员将在收到消息时打印一条消息。
pid:= egine.spawn(newhelloer,“你好”)
这将导致引擎带有ID“ Hello”的演员。演员将由提供的newHelloer
创建。 ID必须是唯一的。它将将指针返回到PID。 PID是过程标识符。这是演员的唯一标识符。大多数时候,您将使用PID向演员发送消息。在远程系统中,您将使用ID发送消息,但是在本地系统上,您将主要使用PID。
让我们看一下newHelloer
函数及其返回的演员。
type Helloer struct {} func newhelloer()actor.receiver {return&Helloer {} }
足够简单。 newHelloer
功能返回新演员。演员是实现Actor.receiver的结构。让我们看看Receive
方法。
类型消息struct {} func(h *helloer)接收(ctx *actor.context){switch msg:= ctx.message()。演员。开始:fmt.println(“ Helloer已经开始”)案例演员。 fmt.println(“ Helloer已停止”)案例 *消息:fmt.println(“ Hello world”,msg.data) } }
您可以看到我们定义了一个消息结构。这是我们稍后将发送给演员的信息。接收方法还处理其他一些消息。这些生命周期消息由引擎发送给演员,您将使用这些消息来初始化您的演员
引擎将Actor.Context传递到Receive
方法。此上下文包含消息,发件人的PID以及您可以使用的其他一些依赖关系。
现在,让我们向演员发送一条消息。我们将发送一条message
,但是您可以发送所需的任何类型的消息。唯一的要求是演员必须能够处理该消息。为了使消息能够越过电线,它们必须是可序列化的。为了使Protobuf能够序列化消息,必须是指针。本地消息可以是任何类型的。
最后,让我们向演员发送一条消息。
Engine.Send(PID,“ Hello World!”)
这将向演员发送一条消息。好莱坞将把消息路由到正确的演员。然后,演员将向控制台打印一条消息。
示例文件夹是进一步学习和探索好莱坞的最佳场所。
当您产生演员时,您需要提供一个返回新演员的功能。由于演员是产卵的,您可以提供一些可调选项。
E.Spawn(newfoo,“ myactorname”)
有时,您需要将论点传递给演员构造函数。这可以通过使用闭合来完成。请求示例中有一个示例。让我们看一下代码。
默认构造函数将看起来像这样:
func newnameresponder()actor.receiver {return&nameresponder {name:“ noname”} }
要构建一个名称的新演员,您可以执行以下操作:
func newcustomnameresponder(name string)actor.producer {return func()actor.receiver {return&nameresponder {name} } }
然后,您可以使用以下代码产生演员:
pid:= egine.spawn(newcustomnameresponder(“ Anthony”),“名称响应器”)
E.Spawn(newfoo,“ myactorname”,Actor.withmaxrestarts(4),Actor.withinboxsize(1024 * 2),actor.withid(“ bar”), ) )
选项应该是非常自我解释的。您可以设置最大重新启动数量,该重新启动数告诉引擎在恐慌的情况下应重新启动给定演员多少次,这是收件箱的大小,这设定了收件箱可以在启动之前可以保持的如何和未加工的消息限制阻止。
没有状态的演员可以作为功能产生,因为它快速而简单。
e.SpawnFunc(func(c *actor.context){switch msg:= c.message()。 } },“ foo”)
演员可以通过网络与远程软件包相互通信。这与本地演员相同,但“在电线上”。好莱坞支持Protobuf序列化。
remote.new()获取一个收听地址和一个远程config struct。
您将使用以下代码实例化新遥控器:
tlsconfig:= tlsconfig:&tls.config {证书:[] tls.certificate {cert}, } config:= remote.newconfig()。使用tls(tlsconfig)远程:= remote.new(“ 0.0.0.0.0:2222”,config),ERGEN,err:= actor..newengine(actor.newengineconeconfig() )
查看远程演员示例和聊天客户端和服务器以获取更多信息。
在生产系统中,事情最终会出错。演员将崩溃,机器将失败,消息将最终进入无生命队列。您可以使用事件流构建可以以优雅且可预测的方式处理这些事件的软件。
EventsTream是一个强大的抽象,可让您在没有依赖性的情况下构建灵活且可插入的系统。
将任何演员订阅到系统事件的各种列表中
向所有订户广播您的自定义活动
请注意,任何演员都没有处理的事件将被丢弃。您应该有一个演员订阅事件流以接收事件。最低限度,您需要处理DeadLetterEvent
。如果好莱坞未能向演员传达信息,它将向事件流发送DeadLetterEvent
信息。
任何满足actor.LogEvent
接口的事件都将记录到默认记录器,并具有严重性级别,消息和actor.LogEvent
log()
方法设置的事件的属性。
actor.ActorInitializedEvent
,演员已被初始化,但没有处理过其actor.Started message
actor.ActorStartedEvent
,演员已经开始
actor.ActorStoppedEvent
,演员已经停止
actor.DeadLetterEvent
,没有传达给演员的信息
actor.ActorRestartedEvent
,演员在崩溃/恐慌之后重新开始。
actor.RemoteUnreachableEvent
,将电线上的消息发送到无法到达的遥控器上。
cluster.MemberJoinEvent
,新成员加入集群
cluster.MemberLeaveEvent
,一个新成员离开了集群
cluster.ActivationEvent
,在群集上激活了一个新演员
cluster.DeactivationEvent
,演员在群集上停用
有一个EventsTream监视示例,向您展示了如何使用事件流。它具有两个演员,一个是不稳定的,每秒都会崩溃。另一个参与者订阅了事件流,并为不同事件(例如崩溃等)维护一些计数器。
该应用程序将运行几秒钟,而不稳定的演员将毒物毒药。然后,它会用请求查询监视器。随着演员在引擎内部漂浮,这就是您与他们互动的方式。然后,MAIN将打印查询结果,并将应用程序退出。
我们正在使用功能选项模式。所有功能选项均在Actor软件包中,并使用“ EngineOpt”启动其名称。当前,唯一的选择是提供遥控器。这是由
r:= remote.new(remote.config {listeraddr:addr})引擎,err:= actor.newengine(actor.enegineoptremote(r))
ADDR是带有格式“主机:端口”的字符串。
您可以将自定义中间件添加到接收器中。这对于在actor.Started
和actor.Stopped
上存储指标,保存和加载数据很有用。
有关如何实现自定义中间件的示例,请查看示例中的中间件文件夹
好莱坞有一些内置的伐木。它将使用log/slog
软件包中的默认记录器。您可以使用slog.SetDefaultLogger()
设置默认记录器,将记录器配置为您的喜好。这将使您可以自定义日志级别,格式和输出。有关更多信息,请参阅slog
软件包”。
请注意,某些事件可能会记录到默认记录器,例如DeadLetterEvent
和ActorStartedEvent
因为这些事件满足了actor.LogEvent
界面。有关更多信息,请参见上面的EventStream部分。
make test
加入我们的Discord社区,与2000多名成员进行问题和聊天良好。
该项目目前由以下组织/项目用于生产:
感官物联网
好莱坞已获得MIT许可证的许可。