#actix-actor #actix #actor #microservices #rpc #api

june

通过actix和canary实现人体工程学的远程actor

1个不稳定版本

0.1.0 2022年6月4日

#1410 in 异步

MIT 协议

15KB
283

六月

June是一个用于分布式系统的远程actor库。

它被设计得尽可能不干扰,其开发体验与使用原始actix(因为它使用actix进行重负载)极为相似。

开始使用远程actor需要了解一些基本知识。

// everything in this specific part is what you would normally do
// while working with actix. In case of any doubt in this part, you should
// look at the docs from actix.

// we'll first define a normal actix actor
struct MyActor {
    count: u64,
}
// declare the actor and its context
impl Actor for MyActor {
    type Context = Context<Self>;
}

// Declare `Increase` message.
// Messages need to implement Serialize and Deserialize
// to be able to be sent and received in remote actors.
#[derive(Message, Serialize, Deserialize)]
#[rtype(result = "u64")]
struct Increase(u64);

/// Handler for `Increase` message
impl Handler<Increase> for MyActor {
    type Result = u64;

    fn handle(&mut self, msg: Increase, _: &mut Context<Self>) -> Self::Result {
        self.count += msg.0;
        println!("Increased. Count: {}", self.count);
        self.count
    }
}


// Declare `Reduce` message
#[derive(Message, Serialize, Deserialize)]
#[rtype(result = "u64")]
struct Reduce(u64);

/// Handler for `Reduce` message
impl Handler<Reduce> for MyActor {
    type Result = u64;

    fn handle(&mut self, msg: Reduce, _c: &mut Self::Context) -> Self::Result {
        self.count -= msg.0;
        println!("decreased. count: {}", self.count);
        self.count
    }
}

在声明actor及其消息后,我们可以通过june远程使用它。

// start by declaring a remote, which is a wrapper that encapsulates all messages
// that can be sent remotely.
remote! {
    remote MyRoute (MyActor) => { // <vis> remote <name> (<actor name>) => { <all messages> }
        Reduce,
        Increase,
    }
}

// now we can expose an actor
async fn server() -> Result<()> {
    let addr = MyActor { count: 0 }.start();

    let tcp = canary::Tcp::bind("127.0.0.1:8080").await?;
    while let Ok(hs) = tcp.next().await {
        let addr = addr.clone();
        tokio::spawn(async move {
            let mut chan = hs.encrypted().await.unwrap();
            june::expose_actor::<_, MyRoute>(&addr, &mut chan)
                .await
                .ok();
        });
    }
    Ok(())
}

// and we can now dial the actor we exposed
async fn client() -> Result<()> {
    let chan: canary::Channel = Tcp::connect("127.0.0.1:8080").await?.encrypted().await?;
    let actor: Addr<MyActor, MyRoute> = Addr::new(chan);
    let res = actor.send(Increase(10)).await?;
    Ok(())
}

June还提供了一种maquio-routing特性,它使与maquio路由器一起工作的特性更加人体工程学。

依赖项

~9–24MB
~315K SLoC