1 个不稳定版本

0.9.0 2020年1月18日

#1040异步


2 crates 中使用

MIT/Apache

225KB
5K SLoC

Actix 构建状态 构建状态 codecov 加入 https://gitter.im/actix/actix 的聊天

Actix 是一个 Rust Actor 框架。


功能

  • 异步/同步 Actor。
  • 本地/线程上下文中的 Actor 通信。
  • 使用 Futures 进行异步消息处理。
  • HTTP1/HTTP2 支持 (actix-web)
  • Actor 监督。
  • 类型化消息(无 Any 类型)。

用法

要使用 actix,将以下内容添加到您的 Cargo.toml

[dependencies]
actix = "0.9"

初始化 Actix

为了使用 actix,您首先需要创建一个 System

fn main() {
    let system = actix::System::new("test");

    system.run();
}

Actix使用了tokio事件循环。System::new()创建了一个新的事件循环并启动了System演员。system.run()启动了tokio事件循环,一旦System演员收到SystemExit消息,则结束。

让我们创建一个简单的Actor。

实现Actor

为了定义一个actor,你需要定义一个struct,并让它实现Actor特质。

use actix::{Actor, Addr, Arbiter, Context, System};

struct MyActor;

impl Actor for MyActor {
    type Context = Context<Self>;

    fn started(&mut self, ctx: &mut Self::Context) {
       println!("I am alive!");
       System::current().stop(); // <- stop system
    }
}

fn main() {
    let system = System::new("test");

    let addr = MyActor.start();

    system.run();
}

通过Actor特质的startcreate方法来创建一个新的actor。它提供了创建actor的多种方式,具体详情请查看文档。你可以实现Actor特质的startedstoppingstopped方法。started在actor启动时被调用,stopping在actor结束时被调用。查看API文档了解更多关于actor生命周期的信息。

处理消息

Actor通过发送消息与其他Actor进行通信。在actix中,所有消息都是类型化的。让我们定义一个简单的带有两个usize参数的Sum消息,并创建一个接受这个消息并返回这两个数字之和的actor。

use futures::{future, Future};
use actix::*;

// this is our Message
struct Sum(usize, usize);

// we have to define the response type for `Sum` message
impl Message for Sum {
    type Result = usize;
}

// Actor definition
struct Summator;

impl Actor for Summator {
    type Context = Context<Self>;
}

// now we need to define `MessageHandler` for the `Sum` message.
impl Handler<Sum> for Summator {
    type Result = usize;   // <- Message response type

    fn handle(&mut self, msg: Sum, ctx: &mut Context<Self>) -> Self::Result {
        msg.0 + msg.1
    }
}

fn main() {
    let sys = System::new("test");

    let addr = Summator.start();
    let res = addr.send(Sum(10, 5));  // <- send message and get future for result

    Arbiter::spawn(res.then(|res| {
        match res {
            Ok(result) => println!("SUM: {}", result),
            _ => println!("Something wrong"),
        }

        System::current().stop();
        future::result(Ok(()))
    }));

    sys.run();
}

所有与actor的通信都通过一个Addr对象进行。你可以使用do_send发送消息而不等待响应,或者使用特定消息发送actor。Message特质定义了消息的结果类型。

Actor状态和特定消息的订阅

你可能已经注意到,ActorHandler特质的 方法接受&mut self,因此你可以将任何东西存储在actor中,并在必要时对其进行修改。

地址对象需要一个actor类型,但如果我们只想向可以处理该消息的actor发送特定消息,我们可以使用Recipient接口。让我们创建一个新的使用Recipient的actor。

use std::time::Duration;
use actix::prelude::*;

#[derive(Message)]
struct Ping { pub id: usize }

// Actor definition
struct Game {
    counter: usize,
    addr: Recipient<Ping>,
}

impl Actor for Game {
    type Context = Context<Game>;
}

// simple message handler for Ping message
impl Handler<Ping> for Game {
    type Result = ();

    fn handle(&mut self, msg: Ping, ctx: &mut Context<Self>) {
        self.counter += 1;

        if self.counter > 10 {
            System::current().stop();
        } else {
            println!("Ping received {:?}", msg.id);

            // wait 100 nanos
            ctx.run_later(Duration::new(0, 100), move |act, _| {
                act.addr.do_send(Ping{id: msg.id + 1});
            });
        }
    }
}

fn main() {
    let system = System::new("test");

    // To get a Recipient object, we need to use a different builder method
    // which will allow postponing actor creation
    let addr = Game::create(|ctx| {
        // now we can get an address of the first actor and create the second actor
        let addr = ctx.address();
        let addr2 = Game{counter: 0, addr: addr.recipient()}.start();

        // let's start pings
        addr2.do_send(Ping{id: 10});

        // now we can finally create first actor
        Game{counter: 0, addr: addr2.recipient()}
    });

    system.run();
}

聊天示例

有一个聊天示例,它提供了一个基本示例,展示了网络客户端/服务器服务。

fectl

你可以考虑查看fectl工具。它使用actix编写,展示了如何创建具有相对复杂交互的网络应用程序。

贡献

所有贡献都受欢迎,如果你有一个功能请求,请毫不犹豫地打开一个问题!

许可协议

本项目采用以下任一许可协议:

任选其一。

行为准则

对actix crate的贡献是在贡献者公约的条款下组织的,actix的维护者@fafhrd91承诺将介入以维护该行为准则。

依赖关系

~7–11MB
~212K SLoC