入门
让我们来创建并运行第一个 actix 应用程序。我们会创建一个新的依赖于 actix 的 Cargo 项目,然后运行该应用程序。
在上一节中,我们已经安装了所需的 rust 版本。现在来创建新的 cargo 项目。
Ping 参与者
我们来写第一个 actix 应用程序吧!首先创建一个新的基于二进制的 Cargo 项目并切换到新目录中:
cargo new actor-ping
cd actor-ping
现在,将 actix 添加为项目的依赖,即确保 Cargo.toml 中包含以下内容:
[dependencies]
actix = "0.10.0-alpha.3"
actix-rt = "1.1" # <-- Runtime for actix
我们来创建一个接受 Ping
消息并以 ping 处理后的数字作为响应的参与者。
参与者(actor)是实现 Actor
trait 的类型:
# extern crate actix; use actix::prelude::*; struct MyActor { count: usize, } impl Actor for MyActor { type Context = Context<Self>; } # # fn main() {}
每个参与者都有一个执行上下文,对于 MyActor
我们会使用 Context<A>
。关于参与者上下文的更多信息在下一节中介绍。
现在需要定义参与者需要接受的消息(Message
)。消息可以是实现
Message
trait 的任何类型。
# extern crate actix; use actix::prelude::*; #[derive(Message)] #[rtype(result = "usize")] struct Ping(usize); # # fn main() {}
Message
trait 的主要目的是定义结果类型。Ping
消息定义了
usize
,表示任何可以接受 Ping
消息的参与者都需要返回 usize
值。
最后,需要声明我们的参与者 MyActor
可以接受 Ping
并处理它。
为此,该参与者需要实现 Handler<Ping>
trait。
# extern crate actix; # use actix::prelude::*; # # struct MyActor { # count: usize, # } # impl Actor for MyActor { # type Context = Context<Self>; # } # # struct Ping(usize); # # impl Message for Ping { # type Result = usize; # } # impl Handler<Ping> for MyActor { type Result = usize; fn handle(&mut self, msg: Ping, _ctx: &mut Context<Self>) -> Self::Result { self.count += msg.0; self.count } } # # fn main() {}
就是这样。现在只需要启动我们的参与者并向其发送消息。
启动过程取决于参与者的上下文实现。在本例中我们可以使用基于 tokio/future 的 Context<A>
。可以用 Actor::start()
或者 Actor::create()
来启动。前者用于可以立即创建参与者实例的场景。
后者用于在创建参与者实例之前需要访问上下文对象的场景。对于 MyActor
参与者,我们可以使用 start()
。
所有与参与者的通信都通过地址进行。可以用 do_send
发送一条消息而不等待响应,也可以向一个参与者用 send
发送指定消息。
start()
与 create()
都会返回一个地址对象。
在以下示例中,我们会创建一个 MyActor
参与者并发送一条消息。
Here we use the actix-rt as way to start our System and drive our main Future
so we can easily .await
for the messages sent to the Actor.
# extern crate actix; # extern crate actix_rt; # use actix::prelude::*; # struct MyActor { # count: usize, # } # impl Actor for MyActor { # type Context = Context<Self>; # } # # struct Ping(usize); # # impl Message for Ping { # type Result = usize; # } # impl Handler<Ping> for MyActor { # type Result = usize; # # fn handle(&mut self, msg: Ping, ctx: &mut Context<Self>) -> Self::Result { # self.count += msg.0; # self.count # } # } # #[actix_rt::main] async fn main() { // 启动新的参与者 let addr = MyActor { count: 10 }.start(); // 发送消息并获取结果 future let res = addr.send(Ping(10)).await; // handle() returns tokio handle println!("RESULT: {}", res.unwrap() == 20); // stop system and exit System::current().stop(); }
#[actix_rt::main]
starts the system and block until future resolves.
Ping 示例可在示例目录中找到。