开始

让我们创建并运行我们的第一个actix应用程序。我们将创建一个新的Cargo项目,该项目依赖于actix然后运行应用程序。

在上一节中,我们已经安装了所需的Rust版本 现在让我们创建新的Cargo项目。

Ping actor

让我们来写第一个actix应用程序吧!首先创建一个新的基于二进制的Cargo项目并切换到新目录:

cargo new actor-ping --bin
cd actor-ping

现在,通过确保您的Cargo.toml包含以下内容,将actix添加为项目的依赖项:

[dependencies]
actix = "0.7"

让我们创建一个接受Ping消息的actor,并使用处理的ping数进行响应。

actor是实现Actor trait的类型:

extern crate actix;
use actix::prelude::*;
struct MyActor {
    count: usize,
}
impl Actor for MyActor {
    type Context = Context<Self>;
}
fn main() {}

每个actor都有一个Context, 对于MyActor我们将使用Context<A>。有关actor上下文的更多信息,请参阅下一节。

现在我们需要定义actor需要接受的Message。消息可以是实现Messagetrait的任何类型。

extern crate actix;
use actix::prelude::*;
struct Ping(usize);
impl Message for Ping {
    type Result = usize;
}
fn main() {}

Messagetrait的主要目的是定义结果类型。 Ping消息定义usize,表示任何可以接受Ping消息的actor都需要返回usize值。

最后,我们需要声明我们的actor MyActor可以接受Ping并处理它。为此,actor需要实现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() {}

现在我们只需要启动我们的actor并向其发送消息。启动过程取决于actor的上下文实现。在我们的情况下可以使用Context <A>其基于tokio / future。我们可以用Actor :: start()开始它或者Actor :: create()。第一个是在可以立即创建actor实例时使用的。第二种方法用于我们在创建之前需要访问上下文对象的情况actor实例。对于MyActor actor,我们可以使用start()

与actor的所有通信都通过一个address。你可以do_send一条消息无需等待响应,或send给具有特定消息的actorstart()create()都返回一个address对象。

在下面的示例中,我们将创建一个MyActor actor并发送一条消息。

extern crate actix;
extern crate futures;
use futures::Future;
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() {
    let system = System::new("test");
    // start new actor
    let addr = MyActor{count: 10}.start();
    // send message and get future for result
    let res = addr.send(Ping(10));
    Arbiter::spawn(
        res.map(|res| {
            # System::current().stop();
            println!("RESULT: {}", res == 20);
        })
        .map_err(|_| ()));
    system.run();
}

Ping示例位于示例中。