Rust高级编程教程

教程简介

面向有基础的Rust高级编程教程,深入讲解生命周期、trait高级用法、并发编程、异步编程(tokio)、宏编程、unsafe Rust、FFI跨语言调用、性能优化等进阶内容,配有高性能HTTP服务器实战项目。

Rust 高级编程教程

本教程面向已有 Rust 基础的开发者,深入探讨生命周期、trait 高级用法、并发编程、异步编程、宏编程、unsafe Rust、FFI 跨语言调用以及性能优化等进阶主题。


目录

  1. 生命周期深入
  2. Trait 高级用法
  3. 并发编程
  4. 异步编程
  5. 宏编程
  6. Unsafe Rust
  7. FFI 跨语言调用
  8. 性能优化
  9. 实战项目:高性能 Web 服务器

1. 生命周期深入

1.1 生命周期的本质

生命周期是 Rust 编译器用来追踪引用有效性的静态分析工具。它不改变程序运行时行为,而是在编译期确保所有引用都是有效的。

// 生命周期标注的基本形式
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}

1.2 结构体中的生命周期

当结构体持有引用时,必须标注生命周期:

struct Excerpt<'a> {
    part: &'a str,
}

impl<'a> Excerpt<'a> {
    // 方法中的生命周期可以省略,编译器自动推断
    fn level(&self) -> i32 {
        3
    }

    // 返回引用时需要明确生命周期关系
    fn announce_and_return(&self, announcement: &str) -> &str {
        println!("注意: {}", announcement);
        self.part
    }
}

1.3 生命周期省略规则(Lifetime Elision)

编译器遵循三条规则自动推断生命周期:

  1. 每个引用参数都获得各自的生命周期
  2. 若只有一个输入生命周期,该生命周期赋给所有输出引用
  3. 若有 &self&mut selfself 的生命周期赋给所有输出引用
// 以下两个签名等价
fn first_word(s: &str) -> &str { /* ... */ }
fn first_word_explicit<'a>(s: &'a str) -> &'a str { /* ... */ }

1.4 'static 生命周期

'static 表示引用在程序整个运行期间有效:

// 字符串字面量具有 'static 生命周期
let s: &'static str = "我活在整个程序运行期间";

// 在 trait bound 中使用 'static
fn print_static<T: Display + 'static>(t: T) {
    println!("{}", t);
}

1.5 高阶生命周期(HRTB)

高阶 trait bound 允许对任意生命周期进行约束:

// for<'a> 表示"对于任意生命周期 'a"
trait Parser {
    fn parse<'a>(&self, input: &'a str) -> &'a str;
}

// 高阶生命周期约束
fn apply_parser<F>(f: F, s: &str) -> &str
where
    F: for<'a> Fn(&'a str) -> &'a str,
{
    f(s)
}

2. Trait 高级用法

2.1 关联类型 vs 泛型参数

关联类型让每个实现只有一种选择,泛型参数允许一个类型对同一 trait 有多种实现:

// 关联类型 — 每个类型只能有一个 Iterator 实现
trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}

// 泛型参数 — 一个类型可以有多个 From 实现
trait From<T> {
    fn from(value: T) -> Self;
}

struct MyType;

impl From<i32> for MyType {
    fn from(v: i32) -> Self { MyType }
}

impl From<String> for MyType {
    fn from(v: String) -> Self { MyType }
}

2.2 默认方法与方法覆盖

trait Summary {
    fn summarize_author(&self) -> String;

    // 默认实现,可被覆盖
    fn summarize(&self) -> String {
        format!("(来自 {} 的摘要...)", self.summarize_author())
    }
}

struct Article {
    title: String,
    author: String,
}

impl Summary for Article {
    fn summarize_author(&self) -> String {
        self.author.clone()
    }
    // summarize() 使用默认实现
}

2.3 Trait 对象与动态分发

// 使用 dyn Trait 进行动态分发
trait Draw {
    fn draw(&self);
}

struct Circle;
struct Square;

impl Draw for Circle {
    fn draw(&self) { println!("绘制圆形"); }
}
impl Draw for Square {
    fn draw(&self) { println!("绘制正方形"); }
}

// Trait 对象的 Vec
fn draw_all(shapes: &[Box<dyn Draw>]) {
    for shape in shapes {
        shape.draw();
    }
}

fn main() {
    let shapes: Vec<Box<dyn Draw>> = vec![
        Box::new(Circle),
        Box::new(Square),
        Box::new(Circle),
    ];
    draw_all(&shapes);
}

2.4 孤儿规则与 Newtype 模式

// 孤儿规则:不能为外部类型实现外部 trait
// 解决方案:Newtype 模式
struct Wrapper(Vec<String>);

impl std::fmt::Display for Wrapper {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "[{}]", self.0.join(", "))
    }
}

2.5 负向约束与 Auto Traits

// Auto traits 自动实现
// Send: 可以安全地在线程间转移所有权
// Sync: 可以安全地在线程间共享引用

// 使用负向约束 opt-out
struct NotThreadSafe {
    data: *const u8,  // 裸指针既不是 Send 也不是 Sync
}

// 手动实现 Send(需要 unsafe)
unsafe impl Send for NotThreadSafe {}
// 不实现 Sync — 不能跨线程共享引用

3. 并发编程

3.1 创建线程

use std::thread;

fn main() {
    // 基本线程创建
    let handle = thread::spawn(|| {
        for i in 1..=5 {
            println!("子线程: {}", i);
            thread::sleep(std::time::Duration::from_millis(100));
        }
    });

    // 使用 move 闭包转移所有权
    let data = vec![1, 2, 3];
    let handle2 = thread::spawn(move || {
        println!("子线程获得数据: {:?}", data);
    });

    handle.join().unwrap();
    handle2.join().unwrap();
}

3.2 消息传递 — Channel

use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn main() {
    let (tx, rx) = mpsc::channel();

    // 多生产者 — 克隆发送端
    let tx2 = tx.clone();

    thread::spawn(move || {
        let messages = vec!["你好", "来自", "线程1"];
        for msg in messages {
            tx.send(msg).unwrap();
            thread::sleep(Duration::from_millis(200));
        }
    });

    thread::spawn(move || {
        let messages = vec!["消息", "来自", "线程2"];
        for msg in messages {
            tx2.send(msg).unwrap();
            thread::sleep(Duration::from_millis(300));
        }
    });

    // 接收所有消息
    for received in rx {
        println!("收到: {}", received);
    }
}

3.3 共享状态 — Mutex 和 Arc

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    // Arc<Mutex<T>> 是多线程共享可变状态的标准模式
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("最终计数: {}", *counter.lock().unwrap());
}

3.4 RwLock — 读写锁

use std::sync::{Arc, RwLock};
use std::thread;

fn main() {
    let data = Arc::new(RwLock::new(vec![1, 2, 3]));
    let mut handles = vec![];

    // 多个读者可以同时持有读锁
    for i in 0..3 {
        let data = Arc::clone(&data);
        handles.push(thread::spawn(move || {
            let read = data.read().unwrap();
            println!("读者 {} 看到: {:?}", i, *read);
        }));
    }

    // 写者需要独占
    {
        let data = Arc::clone(&data);
        handles.push(thread::spawn(move || {
            let mut write = data.write().unwrap();
            write.push(4);
            println!("写者添加了元素");
        }));
    }

    for h in handles {
        h.join().unwrap();
    }
}

3.5 原子类型

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread;

fn main() {
    let counter = Arc::new(AtomicUsize::new(0));
    let mut handles = vec![];

    for _ in 0..100 {
        let counter = Arc::clone(&counter);
        handles.push(thread::spawn(move || {
            // 原子操作无需锁
            counter.fetch_add(1, Ordering::SeqCst);
        }));
    }

    for h in handles { h.join().unwrap(); }
    println!("原子计数: {}", counter.load(Ordering::SeqCst));
}

4. 异步编程

4.1 async/await 基础

// async fn 返回一个 Future,惰性执行
async fn fetch_data(url: &str) -> Result<String, reqwest::Error> {
    let body = reqwest::get(url).await?.text().await?;
    Ok(body)
}

// 需要一个异步运行时(如 tokio)来驱动 Future
#[tokio::main]
async fn main() {
    match fetch_data("https://httpbin.org/get").await {
        Ok(data) => println!("获取到 {} 字节", data.len()),
        Err(e) => eprintln!("错误: {}", e),
    }
}

4.2 Future 的本质

use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

// Future 是一个惰性状态机
struct CountDown {
    count: u32,
}

impl Future for CountDown {
    type Output = String;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        if self.count == 0 {
            Poll::Ready("倒计时完成!".to_string())
        } else {
            println!("{}", self.count);
            self.count -= 1;
            // 唤醒器通知运行时再次轮询
            cx.waker().wake_by_ref();
            Poll::Pending
        }
    }
}

4.3 并发任务

use tokio::time::{sleep, Duration};

async fn task(name: &str, ms: u64) -> String {
    sleep(Duration::from_millis(ms)).await;
    format!("{} 完成", name)
}

#[tokio::main]
async fn main() {
    // 并发执行多个 Future
    let (a, b, c) = tokio::join!(
        task("任务A", 100),
        task("任务B", 200),
        task("任务C", 150),
    );
    println!("{}, {}, {}", a, b, c);

    // 选择第一个完成的
    let result = tokio::select! {
        val = task("快", 100) => val,
        val = task("慢", 500) => val,
    };
    println!("最快完成: {}", result);
}

4.4 Spawn 与任务管理

#[tokio::main]
async fn main() {
    let mut handles = vec![];

    for i in 0..5 {
        // tokio::spawn 创建独立任务,可在不同线程执行
        let handle = tokio::spawn(async move {
            tokio::time::sleep(tokio::time::Duration::from_millis(100 * i)).await;
            format!("任务 {} 完成", i)
        });
        handles.push(handle);
    }

    for handle in handles {
        let result = handle.await.unwrap();
        println!("{}", result);
    }
}

4.5 异步 Channel

use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
    // 有界通道 — 背压控制
    let (tx, mut rx) = mpsc::channel(32);

    for i in 0..5 {
        let tx = tx.clone();
        tokio::spawn(async move {
            tx.send(format!("消息 {}", i)).await.unwrap();
        });
    }
    drop(tx); // 关闭发送端以结束接收循环

    while let Some(msg) = rx.recv().await {
        println!("收到: {}", msg);
    }
}

4.6 异步 Mutex 与同步原语

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

#[tokio::main]
async fn main() {
    // tokio::sync::Mutex 在 .lock().await 时不会阻塞线程
    let data = Arc::new(Mutex::new(Vec::new()));

    let mut handles = vec![];
    for i in 0..5 {
        let data = Arc::clone(&data);
        handles.push(tokio::spawn(async move {
            let mut vec = data.lock().await;
            vec.push(i);
        }));
    }

    for h in handles { h.await.unwrap(); }
    println!("结果: {:?}", *data.lock().await);
}

5. 宏编程

5.1 声明宏(macro_rules!)

// 基本的声明宏
macro_rules! say_hello {
    () => {
        println!("你好!");
    };
    ($name:expr) => {
        println!("你好, {}!", $name);
    };
}

// 可变参数宏
macro_rules! vec_of_strings {
    ($($s:expr),* $(,)?) => {
        vec![$($s.to_string()),*]
    };
}

// 重复模式匹配
macro_rules! hash_map {
    ($( $key:expr => $value:expr ),* $(,)?) => {
        {
            let mut map = std::collections::HashMap::new();
            $( map.insert($key, $value); )*
            map
        }
    };
}

fn main() {
    say_hello!();
    say_hello!("世界");

    let names = vec_of_strings!["Alice", "Bob", "Charlie"];
    println!("{:?}", names);

    let scores = hash_map! {
        "数学" => 95,
        "英语" => 88,
        "物理" => 92,
    };
    println!("{:?}", scores);
}

5.2 自定义 derive 宏

// 使用 proc_macro 定义 derive 宏
// 在独立的 proc-macro crate 中:

use proc_macro::TokenStream;
use quote::quote;
use syn;

#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    impl_hello_macro(&ast)
}

fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
    let name = &ast.ident;
    let gen = quote! {
        impl HelloMacro for #name {
            fn hello_macro() {
                println!("你好!我是 {}", stringify!(#name));
            }
        }
    };
    gen.into()
}

5.3 属性宏与函数式过程宏

// 属性宏示例
#[proc_macro_attribute]
pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
    let input = syn::parse_macro_input!(item as syn::ItemFn);
    let route_path = attr.to_string();

    let fn_name = &input.sig.ident;
    let fn_body = &input.block;

    let output = quote! {
        pub fn #fn_name() -> Route {
            Route::new(#route_path, || #fn_body)
        }
    };
    output.into()
}

// 使用:
// #[route("/hello")]
// fn hello_handler() -> String { "Hello!".to_string() }

6. Unsafe Rust

6.1 Unsafe 的能力与责任

fn main() {
    // unsafe 块允许以下五种操作:
    // 1. 解引用裸指针
    let mut num = 5;
    let r1 = &num as *const i32;
    let r2 = &mut num as *mut i32;
    unsafe {
        println!("r1: {}", *r1);
        *r2 = 10;
        println!("r2: {}", *r2);
    }

    // 2. 调用 unsafe 函数或方法
    unsafe {
        dangerous_function();
    }

    // 3. 访问或修改可变静态变量
    println!("COUNTER: {}", COUNTER);

    // 4. 实现 unsafe trait
    // 5. 访问 union 的字段
}

unsafe fn dangerous_function() {
    println!("这是一个 unsafe 函数");
}

static mut COUNTER: u32 = 0;

fn add_to_counter(inc: u32) {
    unsafe {
        COUNTER += inc;
    }
}

6.2 安全抽象封装 Unsafe

// 将 unsafe 操作封装在安全接口中
pub struct SafeBuffer {
    ptr: *mut u8,
    len: usize,
    capacity: usize,
}

impl SafeBuffer {
    pub fn new(capacity: usize) -> Self {
        let layout = std::alloc::Layout::array::<u8>(capacity).unwrap();
        let ptr = unsafe { std::alloc::alloc(layout) };
        if ptr.is_null() {
            std::alloc::handle_alloc_error(layout);
        }
        SafeBuffer { ptr, len: 0, capacity }
    }

    pub fn push(&mut self, byte: u8) {
        assert!(self.len < self.capacity, "缓冲区已满");
        unsafe {
            self.ptr.add(self.len).write(byte);
        }
        self.len += 1;
    }

    pub fn get(&self, index: usize) -> Option<u8> {
        if index < self.len {
            Some(unsafe { *self.ptr.add(index) })
        } else {
            None
        }
    }
}

impl Drop for SafeBuffer {
    fn drop(&mut self) {
        let layout = std::alloc::Layout::array::<u8>(self.capacity).unwrap();
        unsafe {
            std::alloc::dealloc(self.ptr, layout);
        }
    }
}

6.3 裸指针与类型转换

fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
    let len = slice.len();
    let ptr = slice.as_mut_ptr();
    assert!(mid <= len);

    unsafe {
        (
            std::slice::from_raw_parts_mut(ptr, mid),
            std::slice::from_raw_parts_mut(ptr.add(mid), len - mid),
        )
    }
}

7. FFI 跨语言调用

7.1 从 Rust 调用 C 函数

// 声明外部 C 函数
extern "C" {
    fn abs(input: i32) -> i32;
    fn sqrt(input: f64) -> f64;
}

fn main() {
    let x = -42;
    let y = 16.0_f64;

    unsafe {
        println!("|{}| = {}", x, abs(x));
        println!("√{} = {}", y, sqrt(y));
    }
}

7.2 从 C 调用 Rust 函数

// 导出给 C 的函数
#[no_mangle]
pub extern "C" fn rust_add(a: i32, b: i32) -> i32 {
    a + b
}

#[no_mangle]
pub extern "C" fn rust_greet(name: *const std::ffi::c_char) {
    let c_str = unsafe { std::ffi::CStr::from_ptr(name) };
    if let Ok(name) = c_str.to_str() {
        println!("你好, {}!", name);
    }
}

// Cargo.toml:
// [lib]
// crate-type = ["cdylib", "staticlib"]

7.3 与 C 交互的字符串处理

use std::ffi::{CString, CStr};
use std::os::raw::c_char;

extern "C" {
    fn getenv(name: *const c_char) -> *mut c_char;
}

fn get_env_var(name: &str) -> Option<String> {
    let c_name = CString::new(name).ok()?;
    unsafe {
        let ptr = getenv(c_name.as_ptr());
        if ptr.is_null() {
            None
        } else {
            CStr::from_ptr(ptr).to_str().ok().map(String::from)
        }
    }
}

fn main() {
    if let Some(path) = get_env_var("PATH") {
        println!("PATH = {}", path);
    }
}

7.4 Rust 与 Python 交互(PyO3)

// 使用 PyO3 库(需要添加依赖)
use pyo3::prelude::*;

#[pyfunction]
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
    Ok((a + b).to_string())
}

#[pyclass]
struct Counter {
    #[pyo3(get)]
    value: i64,
}

#[pymethods]
impl Counter {
    #[new]
    fn new() -> Self {
        Counter { value: 0 }
    }

    fn increment(&mut self) {
        self.value += 1;
    }
}

#[pymodule]
fn my_rust_lib(m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
    m.add_class::<Counter>()?;
    Ok(())
}

8. 性能优化

8.1 迭代器与零成本抽象

fn main() {
    let numbers: Vec<i64> = (1..=1_000_000).collect();

    // 迭代器链 — 编译后等价于手写循环,无额外开销
    let sum: i64 = numbers.iter()
        .filter(|&&x| x % 2 == 0)
        .map(|&x| x * x)
        .sum();

    // vs 传统循环(性能几乎相同)
    let mut sum2: i64 = 0;
    for &n in &numbers {
        if n % 2 == 0 {
            sum2 += n * n;
        }
    }

    assert_eq!(sum, sum2);
}

8.2 内存布局优化

// 布局不紧凑 — 有填充字节
struct Bad(u8, u64, u8);  // 可能占用 24 字节

// 按大小排列字段 — 减少填充
struct Good(u64, u8, u8);  // 通常只占 16 字节

// 使用 repr 控制内存布局
#[repr(C)]        // C 语言布局,字段按声明顺序排列
struct CLayout {
    a: u8,
    b: u64,
    c: u8,
}

#[repr(packed)]   // 紧凑布局,无填充(可能影响访问性能)
struct Packed {
    a: u8,
    b: u64,
    c: u8,
}

fn main() {
    println!("Bad: {} bytes", std::mem::size_of::<Bad>());
    println!("Good: {} bytes", std::mem::size_of::<Good>());
}

8.3 避免不必要的分配

use std::borrow::Cow;

// Cow — 写时复制,避免不必要的 String 分配
fn process(input: &str) -> Cow<str> {
    if input.contains("bad") {
        // 需要修改 — 分配新的 String
        Cow::Owned(input.replace("bad", "good"))
    } else {
        // 不需要修改 — 借用原始数据
        Cow::Borrowed(input)
    }
}

// 使用 &str 而非 String 作为函数参数
fn count_words(text: &str) -> usize {
    text.split_whitespace().count()
}

// 预分配容量
fn build_string(items: &[&str]) -> String {
    let total_len: usize = items.iter().map(|s| s.len()).sum();
    let mut result = String::with_capacity(total_len);
    for item in items {
        result.push_str(item);
    }
    result
}

8.4 使用 cargo bench 进行基准测试

// 在 Cargo.toml 中添加:
// [dev-dependencies]
// criterion = "0.5"
//
// [[bench]]
// name = "my_bench"
// harness = false

// benches/my_bench.rs
use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn fibonacci(n: u64) -> u64 {
    match n {
        0 => 1,
        1 => 1,
        n => fibonacci(n - 1) + fibonacci(n - 2),
    }
}

fn criterion_benchmark(c: &mut Criterion) {
    c.bench_function("fib 20", |b| b.iter(|| fibonacci(black_box(20))));
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

8.5 编译优化配置

# Cargo.toml

[profile.release]
opt-level = 3          # 最大优化
lto = true             # 链接时优化
codegen-units = 1      # 单编译单元,更好优化
panic = "abort"        # panic 时直接 abort,减少展开表

[profile.dev]
opt-level = 0          # 开发时快速编译

[profile.bench]
opt-level = 3
lto = true

8.6 SIMD 与数据并行

// 使用 std::simd(nightly)或 packed_simd
// 稳定版可以使用 auto-vectorization

// 编译器自动向量化示例
fn sum_array(data: &[f32]) -> f32 {
    let mut sum = 0.0f32;
    // 简单循环 — 编译器很可能自动向量化
    for &val in data {
        sum += val;
    }
    sum
}

// 使用 chunks 提示编译器进行向量化
fn dot_product(a: &[f32], b: &[f32]) -> f32 {
    assert_eq!(a.len(), b.len());
    a.chunks(4)
        .zip(b.chunks(4))
        .fold(0.0f32, |acc, (ca, cb)| {
            acc + ca.iter().zip(cb.iter()).map(|(x, y)| x * y).sum::<f32>()
        })
}

9. 实战项目:高性能 Web 服务器

下面我们将综合运用以上知识,构建一个基于 tokio 的异步 HTTP 服务器。

9.1 项目结构

my-server/
├── Cargo.toml
├── src/
│   ├── main.rs
│   ├── router.rs
│   ├── handler.rs
│   ├── middleware.rs
│   └── pool.rs

9.2 Cargo.toml 配置

[package]
name = "my-server"
version = "0.1.0"
edition = "2021"

[dependencies]
tokio = { version = "1", features = ["full"] }
bytes = "1"
http = "1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"

[profile.release]
opt-level = 3
lto = true
codegen-units = 1

9.3 核心实现

// src/main.rs
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::{TcpListener, TcpStream};
use std::sync::Arc;
use tokio::sync::RwLock;
use std::collections::HashMap;

type SharedState = Arc<RwLock<HashMap<String, String>>>;

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let listener = TcpListener::bind("127.0.0.1:8080").await?;
    println!("服务器运行在 http://127.0.0.1:8080");

    let state: SharedState = Arc::new(RwLock::new(HashMap::new()));

    loop {
        let (socket, addr) = listener.accept().await?;
        println!("新连接: {}", addr);

        let state = Arc::clone(&state);
        // 每个连接一个独立任务
        tokio::spawn(async move {
            if let Err(e) = handle_connection(socket, state).await {
                eprintln!("处理连接出错: {}", e);
            }
        });
    }
}

async fn handle_connection(
    mut stream: TcpStream,
    state: SharedState,
) -> std::io::Result<()> {
    let mut buffer = vec![0u8; 4096];
    let n = stream.read(&mut buffer).await?;
    if n == 0 { return Ok(()); }

    let request = String::from_utf8_lossy(&buffer[..n]);
    let response = route_request(&request, state).await;

    stream.write_all(response.as_bytes()).await?;
    stream.flush().await?;
    Ok(())
}

async fn route_request(request: &str, state: SharedState) -> String {
    let first_line = request.lines().next().unwrap_or("");
    let parts: Vec<&str> = first_line.split_whitespace().collect();

    if parts.len() < 2 {
        return bad_request();
    }

    let method = parts[0];
    let path = parts[1];

    match (method, path) {
        ("GET", "/") => ok_response("<h1>欢迎使用 Rust 高性能服务器</h1>"),
        ("GET", "/health") => ok_response(r#"{"status":"ok"}"#),
        ("GET", path) if path.starts_with("/api/kv/") => {
            let key = &path[8..];
            let store = state.read().await;
            match store.get(key) {
                Some(val) => ok_response(&format!(r#"{{"{}":"{}"}}"#, key, val)),
                None => not_found(),
            }
        }
        ("POST", "/api/kv") => {
            // 简单解析 JSON body
            if let Some(body_start) = request.find("\r\n\r\n") {
                let body = &request[body_start + 4..];
                if let Ok(map) = serde_json::from_str::<HashMap<String, String>>(body) {
                    let mut store = state.write().await;
                    for (k, v) in map {
                        store.insert(k, v);
                    }
                    return ok_response(r#"{"status":"saved"}"#);
                }
            }
            bad_request()
        }
        _ => not_found(),
    }
}

fn ok_response(body: &str) -> String {
    format!(
        "HTTP/1.1 200 OK\r\nContent-Length: {}\r\nContent-Type: text/html; charset=utf-8\r\nConnection: close\r\n\r\n{}",
        body.len(),
        body
    )
}

fn not_found() -> String {
    "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\nConnection: close\r\n\r\n".to_string()
}

fn bad_request() -> String {
    "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\nConnection: close\r\n\r\n".to_string()
}

9.4 中间件系统

// src/middleware.rs
use std::time::Instant;

/// 请求日志中间件 — 记录每个请求的耗时
pub struct Logger;

impl Logger {
    pub fn log(method: &str, path: &str, status: u16, duration: std::time::Duration) {
        println!(
            "[{}] {} {} - {}ms",
            chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
            method,
            path,
            duration.as_millis()
        );
    }
}

/// 限流中间件 — 使用令牌桶算法
pub struct RateLimiter {
    tokens: tokio::sync::Mutex<f64>,
    max_tokens: f64,
    refill_rate: f64,  // 每秒补充的令牌数
    last_refill: tokio::sync::Mutex<Instant>,
}

impl RateLimiter {
    pub fn new(max_requests_per_second: f64) -> Self {
        RateLimiter {
            tokens: tokio::sync::Mutex::new(max_requests_per_second),
            max_tokens: max_requests_per_second,
            refill_rate: max_requests_per_second,
            last_refill: tokio::sync::Mutex::new(Instant::now()),
        }
    }

    pub async fn check(&self) -> bool {
        let now = Instant::now();
        let mut last = self.last_refill.lock().await;
        let elapsed = now.duration_since(*last).as_secs_f64();
        *last = now;

        let mut tokens = self.tokens.lock().await;
        *tokens = (*tokens + elapsed * self.refill_rate).min(self.max_tokens);

        if *tokens >= 1.0 {
            *tokens -= 1.0;
            true
        } else {
            false
        }
    }
}

9.5 连接池

// src/pool.rs
use tokio::sync::Semaphore;
use std::sync::Arc;

/// 简单的连接池 — 限制并发连接数
pub struct ConnectionPool {
    semaphore: Arc<Semaphore>,
    max_connections: usize,
}

impl ConnectionPool {
    pub fn new(max_connections: usize) -> Self {
        ConnectionPool {
            semaphore: Arc::new(Semaphore::new(max_connections)),
            max_connections,
        }
    }

    pub async fn acquire(&self) -> tokio::sync::OwnedSemaphorePermit {
        self.semaphore
            .clone()
            .acquire_owned()
            .await
            .expect("信号量已关闭")
    }

    pub fn available(&self) -> usize {
        self.semaphore.available_permits()
    }
}

9.6 性能调优建议

┌─────────────────────────────────────────────────────────┐
│                  性能优化检查清单                         │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  1. 编译优化                                              │
│     □ 使用 --release 编译                                │
│     □ 启用 LTO (lto = true)                              │
│     □ 设置 codegen-units = 1                             │
│     □ 使用 panic = "abort"                               │
│                                                         │
│  2. 运行时优化                                            │
│     □ 调整 tokio worker 线程数                            │
│     □ 使用 work-stealing 调度器                           │
│     □ 避免阻塞异步运行时(用 spawn_blocking)              │
│                                                         │
│  3. 内存优化                                              │
│     □ 预分配缓冲区和容器容量                               │
│     □ 使用 Arc 共享不可变数据                              │
│     □ 使用 Bytes 避免拷贝                                 │
│     □ 减少堆分配,使用栈上数据结构                         │
│                                                         │
│  4. I/O 优化                                              │
│     □ 使用 TCP_NODELAY 减少延迟                           │
│     □ 复用连接(Connection: keep-alive)                  │
│     □ 使用 io_uring (Linux) 提升吞吐                      │
│                                                         │
│  5. 监控指标                                              │
│     □ P99 延迟                                           │
│     □ 吞吐量 (requests/sec)                              │
│     □ 内存使用                                            │
│     □ CPU 利用率                                          │
│                                                         │
└─────────────────────────────────────────────────────────┘

9.7 完整的 main.rs 带中间件

use std::sync::Arc;
use tokio::net::TcpListener;

mod middleware;
mod pool;

use middleware::RateLimiter;
use pool::ConnectionPool;

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let listener = TcpListener::bind("127.0.0.1:8080").await?;
    let rate_limiter = Arc::new(RateLimiter::new(1000.0)); // 1000 req/s
    let pool = Arc::new(ConnectionPool::new(10000));       // 最多 10000 并发

    println!("高性能 Rust 服务器启动于 127.0.0.1:8080");
    println!("限流: 1000 req/s | 最大并发: 10000");

    loop {
        let (stream, addr) = listener.accept().await?;
        let limiter = Arc::clone(&rate_limiter);
        let pool = Arc::clone(&pool);

        tokio::spawn(async move {
            // 限流检查
            if !limiter.check().await {
                // 返回 429 Too Many Requests
                return;
            }

            // 获取连接许可
            let _permit = pool.acquire().await;

            // 处理请求...
            let start = std::time::Instant::now();
            // ... 处理逻辑 ...
            let elapsed = start.elapsed();

            middleware::Logger::log("GET", "/", 200, elapsed);
        });
    }
}

总结

本教程涵盖了 Rust 进阶编程的核心主题:

主题 关键要点
生命周期 HRTB、省略规则、'static 语义
Trait 关联类型、动态分发、孤儿规则
并发 线程、Channel、Mutex、原子类型
异步 async/await、Future、tokio 生态
声明宏、过程宏、derive 宏
Unsafe 裸指针、安全抽象、内存操作
FFI C 互操作、PyO3、字符串转换
性能 零成本抽象、内存布局、编译优化

掌握这些进阶知识后,你将能够:

  • 编写安全且高效的并发代码
  • 构建生产级异步服务
  • 设计优雅的 API 与抽象
  • 与 C/C++/Python 等语言无缝集成
  • 对性能进行系统性优化

继续深入的最佳方式是动手实践——尝试构建自己的项目,在真实场景中运用这些知识。


📚 推荐资源

内容声明

本文内容为AI技术学习教程,仅供学习参考。如涉及技术问题,欢迎通过 xurj005@163.com 与我们交流。

目录