宣布tokio-io Crate

今天我们很高兴地宣布一个新的箱子和几个新工具 在Tokio堆栈中。这代表了许多并行的高潮 对各种零碎的更新,它们恰好便于降落 大约在同一时间!简而言之,改进是:

  • tokio-core中提取的新tokio-io箱子,弃用了   [tokio_core :: io]模块。
  • bytes crate引入tokio-io,允许抽象结束   缓冲和利用矢量I / O等基础功能。
  • 在“Sink”特征中添加一种新方法“close”,以表达优雅   关掉。

这些更改改进了Tokio的组织和抽象 几个长期存在的问题,应该为所有人提供稳定的基础 未来的发展。与此同时,这些变化并没有破坏 旧的io模块仍然以不推荐的形式提供。你可以开始全部使用了 这些箱子立即通过cargo update并使用最新的0.1。* 板条箱的版本!

让我们更深入地了解每个细节的变化,看看现在有什么可用。

添加一个tokio-io箱子

现有的[tokio_core :: io]模块提供了许多有用的抽象 但它们并不是tokio-core本身所特有的,也不是它的主要目的 tokio-io crate是提供这些核心实用程序而没有任何含义 运行时。使用tokio-io crates可以依赖于异步I / O语义 而不是将自己绑定到特定的运行时,例如tokio-coretokio-io crate旨在类似于[std :: io]标准 库模块在为异步提供通用抽象方面 生态系统。 tokio-io中提出的概念和特征是基础 对于在Tokio堆栈中完成的所有I / O.

tokio-io的主要内容是AsyncReadAsyncWrite 特征。这两个特征是一种“分裂Io特征”并被选中 划分实现类似Tokio的读/写语义的类型(非阻塞 并通知未来的任务)。然后这些特征与[字节]集成 箱子提供一些方便的功能,并保留旧的功能,如 split

我们还有机会刷新Codec特征 tokio-core crate到EncoderDecoder特征,它们可以运行 bytes crate中的类型(EasyBuftokio-io中不存在,而且它是 现在在tokio-core中弃用了。这些类型允许您快速移动 字节流到SinkStream准备好接受成帧消息。 一个很好的例子就是使用tokio-io我们可以使用新的 length_delimited模块结合tokio-serde-json起床和 我们将在本文后面看到,立即使用JSON RPC服务器运行。

总的来说,tokio-io我们也能够重新审视几个小问题 API设计。这反过来使我们能够[关闭一大堆 问题] [关闭]反对tokio-core。我们觉得tokio-io是一个很好的补充 向前移动的Tokio堆栈。板条箱可以选择抽象 如果他们愿意的话,tokio-io不会像tokio-core那样拉动运行时间。

集成bytes

tokio-core的一个长期疣是它的EasyBuf字节缓冲区类型。 这种类型基本上就是它所说的锡(“简单”缓冲区),但是 遗憾的是,在高性能用例中通常不是您想要的。我们已经 长期以来希望有更好的抽象(以及更好的具体实现) 这里。

使用tokio-io你会发现crates.io上的bytes箱子更多 紧密集成并提供高性能所需的抽象 和“简单”缓冲同时。 bytes箱子的主要内容是 BufBufMut特征。这两个特征充当了能力 任意字节缓冲区(可读和可写)都是抽象的 在所有异步I / O对象上集成了read_bufwrite_buf 现在。

除了用于抽象多种缓冲区的特性bytes crate 有两个高质量的这些特征实现,BytesBytesMut类型(分别实现BufBufMut特征)。 简而言之,这些类型代表允许的引用计数缓冲区 以有效的方式对数据切片进行零拷贝提取。引导他们 还支持各种常见操作,如微小缓冲区(内联 存储),单一所有者(可以在内部使用Vec),共享所有者 不相交的视图(BytesMut),以及可能重叠视图的共享所有者 (Bytes)。

总的来说,我们希望的[字节]包是你的一站式字节缓冲区 抽象以及高质量的实现,让您运行 很快。我们很高兴看到bytes箱子里面有什么东西!

添加Sink :: close

我们最近登陆的最后一个重大变化是增加了一个新的 关于的方法

添加 Sink::close

我们最近登陆的最后一个重大变化是增加了一个新的 Sink特征的方法,close。 到目前为止还不是很好 关于以通用方式实现“优雅关闭”的故事,因为那里 没有干净的方式向水槽表明没有更多的物品被推入 它。 新的close方法正是为此目的而准备的。

close方法允许通知接收器不再有消息 推进去了。 然后,接收器可以借此机会刷新消息 否则执行协议特定的关闭。 例如,TLS连接 该点可能会启动关闭操作或代理连接 发出TCP级别的关闭。 通常情况下,这最终会触底到新的 [AsyncWrite :: shutdown]方法。

添加 codec::length_delimited

使用tokio-io登陆的一个大功能是添加 length_delimited模块(受Netty的启发 [LengthFieldBasedFrameDecoder])。 许多协议使用a来分隔帧 包含帧长度的帧头。 举一个简单的例子,拿一个 使用u32的帧头来划分帧有效载荷的协议。 每 电线上的框架看起来像这样:

+----------+--------------------------------+
| len: u32 |          frame payload         |
+----------+--------------------------------+

解析此协议可以轻松处理

// Bind a server socket
let socket = TcpStream::connect(
    &"127.0.0.1:17653".parse().unwrap(),
    &handle);

socket.and_then(|socket| {
    // Delimit frames using a length header
    let transport = length_delimited::FramedWrite::new(socket);
})

在上面的例子中,transport将是缓冲区的Sink + Stream 值,其中每个缓冲区包含帧有效负载。 这使得 将帧编码和解码为相当容易的值 像[serde]这样的东西。 例如,使用tokio-serde-json,我们可以 快速实现基于JSON的协议,其中每个帧都是长度 分隔,并使用JSON编码帧有效负载:

// Bind a server socket
let socket = TcpStream::connect(
    &"127.0.0.1:17653".parse().unwrap(),
    &handle);

socket.and_then(|socket| {
    // Delimit frames using a length header
    let transport = length_delimited::FramedWrite::new(socket);

    // Serialize frames with JSON
    let serialized = WriteJson::new(transport);

    // Send the value
    serialized.send(json!({
        "name": "John Doe",
        "age": 43,
        "phones": [
            "+44 1234567",
            "+44 2345678"
        ]
    }))
})

完整的例子就在这里

length_delimited模块包含足够的配置设置来处理具有更复杂帧头的解析长度分隔帧,如HTTP / 2.0协议。

下一步是什么?

所有这些变化汇集在一起​​,关闭了期货和托克欧核心板条箱中的大量问题,我们认为Tokio正是我们喜欢的常见I / O和缓冲抽象的位置。一如既往,我们很乐意听到有关问题跟踪器的反馈,如果您发现问题,我们非常愿意合并PR!否则我们期待在实践中看到所有这些变化!

凭借tokio-core,tokio-io,tokio-service和tokio-proto的基础,Tokio团队期待着适应和实施更加雄心勃勃的协议,如HTTP / 2。我们正在与@seanmonstar和Hyper密切合作,以开发这些基础HTTP库。最后,我们希望在不久的将来扩展与HTTP和通用tokio服务实现相关的中间件故事。更多关于这个即将到来!