郭佳恩前端工程师
返回首页
25 分钟阅读技术专栏

构建高性能 Rust 异步运行时

深入理解 Rust 的 async/await 机制。我们将探讨 Future trait 的工作原理,以及如何使用 Tokio 构建高并发网络服务。

RustBackendConcurrencySystems Programming

Rust 的异步模型是 "Zero-cost abstractions" 的典范。

1. Future Trait

Rust 的异步核心是 Future trait。它类似于 JavaScript 的 Promise,但是它是惰性的(Lazy)。

rust
pub trait Future {
    type Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

pub enum Poll<T> {
    Ready(T),
    Pending,
}

除非你通过 .await 或执行器(Executor)去轮询它,否则 Future 什么都不会做。

2. 使用 Tokio 构建 TCP Echo Server

Tokio 是 Rust 最流行的异步运行时。

rust
use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let listener = TcpListener::bind("127.0.0.1:8080").await?;

    loop {
        let (mut socket, _) = listener.accept().await?;

        tokio::spawn(async move {
            let mut buf = [0; 1024];

            // In a loop, read data from the socket and write the data back.
            loop {
                let n = match socket.read(&mut buf).await {
                    // socket closed
                    Ok(n) if n == 0 => return,
                    Ok(n) => n,
                    Err(e) => {
                        eprintln!("failed to read from socket; err = {:?}", e);
                        return;
                    }
                };

                // Write the data back
                if let Err(e) = socket.write_all(&buf[0..n]).await {
                    eprintln!("failed to write to socket; err = {:?}", e);
                    return;
                }
            }
        });
    }
}

3. 在线程间共享状态

使用 ArcMutex 在异步任务间安全地共享状态。

rust
use std::sync::Arc;
use tokio::sync::Mutex;

type Db = Arc<Mutex<HashMap<String, String>>>;

#[tokio::main]
async fn main() {
    let db: Db = Arc::new(Mutex::new(HashMap::new()));

    // ... pass db to handlers
}

评论区0

自由讨论你的想法,分享你的实践。

还没有评论

成为第一个发言的人吧