Rust 高级编程教程
本教程面向已有 Rust 基础的开发者,深入探讨生命周期、trait 高级用法、并发编程、异步编程、宏编程、unsafe Rust、FFI 跨语言调用以及性能优化等进阶主题。
目录
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)
编译器遵循三条规则自动推断生命周期:
- 每个引用参数都获得各自的生命周期
- 若只有一个输入生命周期,该生命周期赋给所有输出引用
- 若有
&self或&mut self,self的生命周期赋给所有输出引用
// 以下两个签名等价
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 等语言无缝集成
- 对性能进行系统性优化
继续深入的最佳方式是动手实践——尝试构建自己的项目,在真实场景中运用这些知识。
📚 推荐资源
- The Rustonomicon — unsafe Rust 的深入指南
- Asynchronous Programming in Rust — 异步编程官方教程
- The Rust Reference — 语言参考手册
- Tokio 官方教程 — 异步运行时文档