Actix学习

版权声明:本文为BBDXF原创,如果转载请注明出处。 https://blog.csdn.net/bbdxf/article/details/87890150

actix 学习

Actix是一个rust库,它为并发应用程序的开发提供了一个框架。
Actix是基于Actor模型构建的,它允许将应用程序编写为一组独立执行但协作的“Actor”,这些“Actor”通过消息进行通信。Actor是封装状态和行为并在actix库提供的Actor系统中运行的对象。
参与者在特定的执行上下文上下文中运行。上下文对象仅在执行期间可用。每个参与者都有一个单独的执行上下文。执行上下文还控制参与者的生命周期。参与者仅通过交换消息进行通信。发送参与者可以选择等待响应。
角色不是直接引用的,而是通过地址引用的。任何rust类型都可以是actor,它只需要实现actor特征。为了能够处理特定的消息,参与者必须为该消息提供一个处理程序实现。所有消息都是静态类型的。消息可以以异步方式处理。
Actor可以生成其他Actor,或者向执行上下文添加期货或流。参与者特征提供了几个方法,允许控制参与者的生命周期。

简单例子

extern crate actix;
extern crate futures;

use std::io;
use actix::prelude::*;
use futures::Future;

/// Define message
struct Ping;

impl Message for Ping {
    type Result = Result<bool, io::Error>;
}


// Define actor
struct MyActor;

// Provide Actor implementation for our actor
impl Actor for MyActor {
    type Context = Context<Self>;

    fn started(&mut self, ctx: &mut Context<Self>) {
        println!("Actor is alive");
    }

    fn stopped(&mut self, ctx: &mut Context<Self>) {
        println!("Actor is stopped");
    }
}

/// Define handler for `Ping` message
impl Handler<Ping> for MyActor {
    type Result = Result<bool, io::Error>;

    fn handle(&mut self, msg: Ping, ctx: &mut Context<Self>) -> Self::Result {
        println!("Ping received");

        Ok(true)
    }
}

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

    // Start MyActor in current thread
    let addr = MyActor.start();

    // Send Ping message.
    // send() message returns Future object, that resolves to message result
    let result = addr.send(Ping);

    // spawn future to reactor
    Arbiter::spawn(
        result.map(|res| {
            match res {
                Ok(result) => println!("Got result: {}", result),
                Err(err) => println!("Got error: {}", err),
            }
            System::current().stop();
        })
            .map_err(|e| {
                println!("Actor is probably died: {}", e);
            }));

    sys.run();
}

通过Arbiter::spawn来产生任务,其中Handler来处理自定义的Actor和Msg。

自定义类型应答

extern crate actix;
extern crate futures;

use actix::dev::{MessageResponse, ResponseChannel};
use actix::prelude::*;
use futures::Future;

enum Messages {
    Ping,
    Pong,
}

enum Responses {
    GotPing,
    GotPong,
}

// 对于Response的相应处理,普通类型不需要,自定义类型需要
impl<A, M> MessageResponse<A, M> for Responses
    where
        A: Actor,
        M: Message<Result=Responses>,
{
    fn handle<R: ResponseChannel<M>>(self, _: &mut A::Context, tx: Option<R>) {
        if let Some(tx) = tx {
            tx.send(self);
        }
    }
}

impl Message for Messages {
    type Result = Responses;
}

// Define actor
struct MyActor;

// Provide Actor implementation for our actor
impl Actor for MyActor {
    type Context = Context<Self>;

    fn started(&mut self, ctx: &mut Context<Self>) {
        println!("Actor is alive");
    }

    fn stopped(&mut self, ctx: &mut Context<Self>) {
        println!("Actor is stopped");
    }
}

/// Define handler for `Messages` enum
impl Handler<Messages> for MyActor {
    type Result = Responses;

    fn handle(&mut self, msg: Messages, ctx: &mut Context<Self>) -> Self::Result {
        match msg {
            Messages::Ping => Responses::GotPing,
            Messages::Pong => Responses::GotPong,
        }
    }
}

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

    // Start MyActor in current thread
    let addr = MyActor.start();

    // Send Ping message.
    // send() message returns Future object, that resolves to message result
    let ping_future = addr.send(Messages::Ping);
    let pong_future = addr.send(Messages::Pong);

    // Spawn pong_future onto event loop
    Arbiter::spawn(
        pong_future
            .map(|res| {
                match res {
                    Responses::GotPing => println!("Ping received"),
                    Responses::GotPong => println!("Pong received"),
                }
                System::current().stop();
            })
            .map_err(|e| {
                println!("Actor is probably died: {}", e);
            }),
    );

    // Spawn ping_future onto event loop
    Arbiter::spawn(
        ping_future
            .map(|res| {
                match res {
                    Responses::GotPing => println!("Ping received"),
                    Responses::GotPong => println!("Pong received"),
                }
                System::current().stop();
            })
            .map_err(|e| {
                println!("Actor is probably died: {}", e);
            }),
    );

    sys.run();
}

猜你喜欢

转载自blog.csdn.net/bbdxf/article/details/87890150