2 个版本
0.1.1 | 2020 年 4 月 6 日 |
---|---|
0.1.0 | 2020 年 4 月 6 日 |
#1985 在 异步
21KB
309 行
stream-body
为 Rust HTTP 库 hyper 提供高效流式支持的 HttpBody 实现。
动机
现有的 hyper 中的 Body 类型使用 Bytes 作为流式块。因此,由于 Bytes 类型,在实时大流量数据传输过程中会发生大量的缓冲区分配和释放。因此,StreamBody
出现来解决这个问题。 StreamBody
实现 HttpBody 并使用 &[u8]
切片作为流式块,因此可以重用相同的缓冲区而无需分配新的缓冲区;因此,它克服了任何分配/释放开销。
此外,hyper Body 中的 channel() 方法返回一对 Sender 和 Body。在这里,Sender 接受 Bytes 作为数据块,这又产生了分配/释放开销。为了解决这个问题,StreamBody
有一个名为 StreamBody::channel()
的方法,该方法返回一对 AsyncWrite 和 StreamBody
本身。由于 AsyncWrite 接受 &[u8]
而不是 Bytes,因此将没有分配/释放开销。
用法
首先将此添加到您的 Cargo.toml 中
[dependencies]
stream-body = "0.1"
处理大文件的示例
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response, Server};
use std::{convert::Infallible, net::SocketAddr};
use stream_body::StreamBody;
use tokio::fs::File;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
async fn handle(_: Request<Body>) -> Result<Response<StreamBody>, Infallible> {
let (mut writer, body) = StreamBody::channel();
tokio::spawn(async move {
let mut f = File::open("large-file").await.unwrap();
// Reuse this buffer
let mut buf = [0_u8; 1024 * 16];
loop {
let read_count = f.read(&mut buf).await.unwrap();
if read_count == 0 {
break;
}
writer.write_all(&buf[..read_count]).await.unwrap();
}
});
Ok(Response::builder().body(body).unwrap())
}
#[tokio::main]
async fn main() {
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let make_svc = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(handle)) });
let server = Server::bind(&addr).serve(make_svc);
if let Err(e) = server.await {
eprintln!("server error: {}", e);
}
}
贡献
您的Pull Requests和星星总是受欢迎的。
依赖项
~4MB
~57K SLoC