我用 Rust 写了一个 Hello World

入职第一天,老板要试一下我的水平,于是给我布置了一个任务,写一个 Hello World吧,但是公司用的是 Rust。

我心想,这不是分分钟的事情嘛,很快程序就写好了:

rust 复制代码
fn main() {
    println!("Hello World!")
}

然后老板说,前端怎么对接你这个接口?啊,你不早说,是写一个接口啊。行吧,那就用 Axum 框架写一个吧,也不是啥难事。虽然不是分分钟,但是三五分钟还是可以搞定的:

rust 复制代码
use axum::Router;
use axum::routing::get;

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", async { "Hello World"});

    let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

然后和老板去回报进度:老板,接口版本的 Hello World 完成了。只见老板眉头一皱:小苏,做一个事情要考虑周全,你这个版本虽然完成了功能,有没有想过安全性呢?给返回 Hello World 加密!

啥!Hello World 也要加密啊,行吧。那就上 AES256-GCM 吧,军规级的,够安全了吧?

rust 复制代码
use aes_gcm::{Aes256Gcm, Key, KeyInit, Nonce};
use hex::encode;

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(encrypted_hello));
    // 省略没有改变的代码
}

async fn encrypted_hello() -> String {
    let message = b"Hello, World!";
    // 省略三五行加密的模版代码,只是为了说明这里实现了加密
    let ciphertext = cipher.encrypt(nonce, message.as_ref()).unwrap();

    format!("encrypted: {}", encode(&ciphertext))
}

心里想,这回老板应该满意了吧。满心欢喜地找老板交差,仿佛升职加薪迎娶老板女儿的日子马上就要到来了。

给老板演示之后,老板欣然一笑,转而又语重心长地说道:安全是安全了,只是......我的心提到了嗓子眼,只是啥?!

老板停顿了好一会,继续说道:只是你有没有考虑过,Axum 是一个协程框架,你将 CPU 密集的计算放在协程里,会不会阻塞?

天啊,流氓不可怕,啊不,老板不可怕,只怕老板懂技术,似懂非懂最可怕。我就写一个 Hello World 而已啊,需要那么复杂嘛?!行,我接着改。

从老板办公室到工位这一路有点漫长,我的脑子飞快地转动着,Axum 框架是基于 Tokio 协程运行时,Tokio 好像提供了一个 API,可以让将一些密集型的代码放到线程里执行......啊,想到了 task::spawn_blocking()!

rust 复制代码
async fn encrypted_hello() -> String {
    task::spawn_blocking(|| {
        let message = b"Hello, World!";
        // 继续省略
        let ciphertext = cipher.encrypt(nonce, message.as_ref()).unwrap();
        format!("encrypted: {}", encode(&ciphertext))
    }).await.unwrap()
}

走,去老板办公室,我得意地一笑,你难不倒我,你女儿迟早是我的。"老板,我想到办法了,把加密的重活交给 tokio 的线程去执行,就不会阻塞协程了!" 老板,看了一眼我,说道:

"你没看到我和小米同学在谈公事嘛,你先出去!"

我瞟了一眼,小米同学是挺漂亮......感性的......

过了大半个小时,老板来到我的工位前,对我说:"这个版本兼顾了安全和性能,还是不错的,但是......"。老板怎么总是喜欢停顿加但是呢?

"但是,你有没有想过,你把密集型计算委托给 Tokio,如果大家都这么做的话,会导致公共线程池饱和......"。老板,这些是 AI 和你说的嘛?

没办法,继续改,既然不能用公共线程池来做,就要自己启用一个线程,然后和协程之间通过 Channel 进行通信......好像有一个东西叫做 mpsc......我只是写一个 Hello World 啊!天啊,迎娶老板女儿啊,不是西天取经啊。

rust 复制代码
use std::thread;
use aes_gcm::{Aes256Gcm, Key, KeyInit, Nonce};
use aes_gcm::aead::Aead;
use axum::Router;
use axum::routing::get;
use hex::encode;
use rand::RngCore;
use rand::rngs::OsRng;
use tokio::sync::{mpsc, oneshot};

struct EncryptTask {
    message: Vec<u8>,
    responder: oneshot::Sender<String>
}

#[tokio::main]
async fn main() {
    let (tx, mut rx) = mpsc::channel::<EncryptTask>(100);

    thread::spawn(move || {
        while let Some(task) = rx.blocking_recv() {
            let key = Key::<Aes256Gcm>::from_slice(&[0u8; 32]);
            let cipher = Aes256Gcm::new(key);

            let mut nonce_bytes = [0u8; 12];
            OsRng.fill_bytes(&mut nonce_bytes);
            let nonce = Nonce::from_slice(&nonce_bytes);

            let ciphertext = cipher.encrypt(nonce, task.message.as_ref()).unwrap();

            let result = format!("nonce: {}, chipher_text: {}", encode(&nonce), encode(&ciphertext));

            let _ = task.responder.send(result);
        }
    });
    let app = Router::new().route("/", get(move || encrypted_hello(tx.clone())));

    let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

async fn encrypted_hello(tx: mpsc::Sender<EncryptTask>) -> String {
    let (resp_tx, resp_rx) = oneshot::channel();
    let task = EncryptTask {
        message: b"Hello World".to_vec(),
        responder: resp_tx,
    };
    tx.send(task).await.unwrap();

    resp_rx.await.unwrap()
}

经过一番折腾,终于完成了。看了一眼窗外,一天过去了,天都黑了。老板和小米同学一前一后走出办公室,正要下班。我抓紧喊了一声,老板我完成了!

老板对我挥了挥手,说道:我想了一下,Hello World 没必要做的那么复杂,你还是改回原来的版本吧.....

相关推荐
a cool fish(无名)3 小时前
rust-方法语法
开发语言·后端·rust
a cool fish(无名)18 小时前
rust-参考与借用
java·前端·rust
叶 落21 小时前
[Rust 基础课程]猜数字游戏-获取用户输入并打印
rust·rust基础
RustFS1 天前
RustFS 如何修改默认密码?
rust
景天科技苑1 天前
【Rust线程池】如何构建Rust线程池、Rayon线程池用法详细解析
开发语言·后端·rust·线程池·rayon·rust线程池·rayon线程池
该用户已不存在2 天前
Zig想要取代Go和Rust,它有资格吗
前端·后端·rust
用户1774125612442 天前
不懂装懂的AI,折了程序员的阳寿
rust
量子位3 天前
vivo自研蓝河操作系统内核开源!Rust开发新机遇来了
rust·ai编程
祈澈菇凉3 天前
rust嵌入式开发零基础入门教程(六)
stm32·单片机·rust
祈澈菇凉3 天前
rust嵌入式开发零基础入门教程(二)
开发语言·后端·rust