本文是对Yoshua Wuyts 博客文章的摘录,以及一些私人观点。原文地址:https://blog.yoshuawuyts.com/async-http/ ,也可点击「阅读原文」跳转。
Async HTTP
async-std 团队的主要开发者yoshuawuyts,联合「 协议实验室」 和 「微软」的另外两人,共同发布了 async http 套件。
主要分为三个库:
1. async-h1 :流式的HTTP/1.1客户端和服务器协议实现
2. http-types :从http服务器(Tide)和客户端框架(Surf)中提取的可重用http类型,是为了共享抽象,减少维护多套代码。
3. async-native-tls :流式TLS客户端和服务器实现,同时支持async-std和tokio。
项目看点
看点一: 流式设计。像处理「水流」一样来处理数据流。
1. 基于 chunked 来实现了流式传输。
Transfer-Encoding: chunked
2. 得益于 Rust 的流处理模型。
在同步Rust中,核心流抽象是迭代器(Iterator)。它提供了一种按顺序 出让(yield)每一项(item),并阻塞了它们。通过将迭代器传递到其他迭代器的构造器(constructors)中来完成组合,从而使我们能够在不费吹灰之力的情况下就将所有内容都组合在一起。
在异步Rust中,核心流抽象是流(Stream)。它的行为与 Iterator 非常相似,但是它不会阻塞每个 item 的 出让(yield),而是允许其他任务在等待时运行。
另外,异步Rust 具有 AsyncRead 和 AsyncWrite 形式的同步读写。这些trait 的目的是表示未解析的字节,通常直接来自IO层(例如来自套接字或文件)。
Rust流具有其他语言的一些最佳特性。例如:通过利用Rust的 trait 系统,它们避免了 Node.js 的 Duplex 流中出现的继承问题。但是它们还实现了背压(back pressure,意思是在数据传输过程中有一大堆数据在缓存之后积压着)和延迟迭代(lazy iteration),从而提高了效率。最重要的是,Rust流允许使用相同的类型进行异步迭代。
参考:
1. https://blog.yoshuawuyts.com/rust-streams/
2. https://nodejs.org/api/stream.html#stream_class_stream_duplex
看点二: AsRef/AsMut 模式应用于多个类型转换(http-types),来自于web-sys中的实践。
在 web-sys 中,可以通过 .as_ref 方法来获取任何一个 父 class 的引用
而在 async-h1 中,对于所有的Request也实现了AsRef<Url>, AsRef<Headers>。这种 「AsRef 模式」让我们可以实现「近似于OOP那样的」继承关系。
看点三: 专门权衡开发体验和性能的API设计。
看点四: 将 HTTP 状态码和错误类型相关联。
对于「分裂生态」言论的回应
介于Rust社区有人一直在说「async-std vs tokio」导致生态分裂的言论,该文章里也有回应:
(个人观点:只是多种解决方案而已,不代表分裂,因为它们还是共同秉持着 Rust 的理念和原则。async-std 和 tokio 都是不错的代表。)
下一步动作
1. 讨论 async-h2 中。
2. 等待 tide 发布 1.0 。tide 是一个基于 async-std 的异步 Web 开发框架,目前tide 已经 0.6 版本了。