这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

Tokio介绍

Tokio的介绍,以及Tokio的资料收集

1 - Tokio概述

Tokio概述

官方介绍

来自 tokio 官网首页 的介绍:

Build reliable network applications without compromising speed.

在不影响速度的情况下建立可靠的网络应用。

Tokio is an asynchronous runtime for the Rust programming language. It provides the building blocks needed for writing network applications. It gives the flexibility to target a wide range of systems, from large servers with dozens of cores to small embedded devices.

Tokio是用于Rust编程语言的一个异步运行时。它提供了编写网络应用所需的构建块。它提供了针对各种系统的灵活性,从有几十个内核的大型服务器到小型嵌入式设备。

声称的主要优势:

  • Reliable/可靠:Tokio 的 API 是内存安全和线程安全的,并且是抗误操作的。这有助于防止常见的错误,如无界队列、缓冲区溢出和任务饿死。
  • Fast/快速:构建在Rust之上,Tokio提供了一个多线程的、抢占式的调度器。应用程序可以每秒处理数十万个请求,而且开销很小。
  • Easy/简单:async/await 减少了编写异步应用程序的复杂性。与Tokio的实用工具和充满活力的生态系统相配,编写应用程序是一件轻而易举的事。
  • Flexible/弹性:服务器应用程序的需求与嵌入式设备的需求不同。尽管Tokio带有默认值可以开箱即用,但它也提供了所需的旋钮,以便对不同的情况进行微调。

技术栈

应用程序不是在真空中建立的。Tokio 技术栈包括交货到生产所需的一切。

  • Runtime: Tokio运行时包括I/O、定时器、文件系统、同步和调度设施,是异步应用的基础。
  • Hyper: Hyper是一个HTTP客户端和服务器库,同时支持HTTP 1和2协议。
  • Tonic: 一个无固定规则(boilerplate-free)的gRPC客户端和服务器库。通过网络发布和使用API的最简单方法。
  • Tower:用于建立可靠的客户端和服务器的模块化组件。包括重试、负载平衡、过滤、请求限制设施等。
  • Mio:在操作系统的事件化I/O API之上的最小的可移植API。
  • Tracing: 对应用程序和库的统一的洞察力。提供结构化的、基于事件的数据收集和记录。
  • Bytes:在核心部分,网络应用程序操纵字节流。Bytes提供了一套丰富的实用程序来操作字节数组。

2 - Tokio术语

Tokio术语

来自:https://tokio.rs/tokio/glossary

异步(Asynchronous)

在Rust的上下文中,异步代码指的是使用async/await语言特性的代码,它允许许多任务在几个线程(甚至是一个单线程)上并发运行。

并发(Concurrency)和并行(Parallelism)

并发和并行是两个相关的概念,在谈论同时执行多个任务时都会用到。如果某件事情是平行发生的,那么它也是并发发生的,但反过来就不是这样了。在两个任务之间交替进行,但实际上从未同时进行两个任务,这就是并发,但不是并行。

未来(Future)

Future是一个存储某些操作的当前状态的值。future也有一个poll方法,它使操作继续进行,直到它需要等待某些东西,比如网络连接。对poll方法的调用应该很快返回。

Future通常是通过在一个异步块中使用.await来组合多个Future来创建的。

执行器(Executor)/调度器(scheduler)

执行器或调度器是通过重复调用poll方法来执行future的东西。标准库中没有执行器,所以你需要一个外部库来实现,而使用最广泛的执行器是由Tokio运行时提供。

执行器能够在几个线程上并发地运行大量的 future。它通过在等待时交换当前运行的任务来做到这一点。如果代码花了很长时间都没有到达 .await,这就被称为 “阻塞线程” 或 “not yielding back to the executor”,这将阻止其他任务的运行。

运行时(Runtime)

运行时是一个库,它包含执行器以及与该执行器集成的各种实用工具,如定时实用工具和IO。运行时和执行器这两个词有时可以互换使用。标准库没有运行时,所以你需要一个外部库来实现,最广泛使用的运行时是 Tokio 运行时。

Runtime这个词也用在其他场合,例如,“Rust没有运行时 “这句话有时被用来表示Rust不执行垃圾收集或即时(just-in-time,JIT)编译。

任务(Task)

任务是在Tokio运行时上运行的操作,由 tokio::spawnRuntime::block_on 函数创建。通过组合创建期货的工具,如 .awaitjoin! 并不创建新的任务,每个组合的部分被说成是 “在同一个任务中”。

多个任务是需要并行的,但使用 join! 等工具可以在一个任务上并发地做多件事情。

spawn

spawn 是指使用 tokio::spawn 函数来创建一个新的任务。它也可以指用std::thread::spoon创建新的线程。

异步块(Async block)

异步块是创建一个运行一些代码的future的简单方法。比如说:

let world = async {
    println!(" world!");
};
let my_future = async {
    print!("Hello ");
    world.await;
};

上面的代码创建了一个名为 my_future 的future,如果执行它,就会打印出 Hello world!。 它是通过首先打印 hello,然后运行 world future来实现的。请注意,上面的代码不会自己打印任何东西–你必须在任何事情发生之前实际执行my_future,要么直接生成(spawn)它,要么在你生成(spawn)的东西中等待它。

异步函数(Async function)

与异步块类似,异步函数是一种创建函数的简单方法,其主体成为一个future。所有的异步函数都可以被改写成返回一个future的普通函数。

async fn do_stuff(i: i32) -> String {
    // do stuff
    format!("The integer is {}.", i)
}
use std::future::Future;

// the async function above is the same as this:
fn do_stuff(i: i32) -> impl Future<Output = String> {
    async move {
        // do stuff
        format!("The integer is {}.", i)
    }
}

这使用 impl Trait 语法来返回一个 future,因为 Future 是一个 trait。请注意,由于由异步块创建的 future 在执行之前不会做任何事情,所以调用异步函数在其返回的 future 被执行之前不会做任何事情(忽略它将触发一个警告)。

让出(Yielding)

在异步Rust的背景下,Yielding是允许执行者在单个线程上执行许多future的原因。每当一个future让出时,执行者能够将该future与其他future交换,通过反复交换当前任务,执行者可以并发地执行大量的任务。future只能在 .await 时让出,所以在 .await 之间花很长时间的future可以阻止其他任务的运行。

具体来说,future只要从 poll 方法中返回就会让出。

阻塞(Blocking)

“阻塞(blocking)“这个词有两种不同的用法: 阻塞的第一个含义是简单地等待某事完成,而阻塞的另一个含义是当一个 future 花很长的时间而不让出。为了明确起见,你可以用 “阻塞线程” 这个短语来表示第二种含义。

Tokio的文档总是使用 “阻塞” 的第二种含义。

要在Tokio中运行阻塞代码,请参见Tokio API参考中的 CPU绑定任务和阻塞代码 部分。

流(Stream)

StreamIterator 的异步版本,它提供了一个数值流。它通常与 while let 循环一起使用,就像这样:

use tokio_stream::StreamExt; // for next()

while let Some(item) = stream.next().await {
    // do something
}

流这个词有时被混乱地用来指代 AsyncReadAsyncWrite 特性。

Tokio的流工具目前是由 tokio-stream crate提供的。一旦Stream特性在std中稳定下来,Stream工具将被移到 tokio crate中。

通道(Channel)

通道是一种工具,允许代码的一个部分向其他部分发送消息。Tokio提供了许多通道,每个通道都有不同的用途:

  • mpsc:多生产者、单消费者通道。可以发送许多值。
  • oneshot:单生产者,单消费者通道。可以发送一个单一的值。
  • broadcast:多生产者,多消费者。可以发送许多值。每个接收者看到每个值。
  • watch:单生产者,多消费者。可以发送许多值,但不保留历史。接收者只看到最新的值。

如果你需要一个多生产者多消费者的通道,每个消息只有一个消费者看到,你可以使用 async-channel crate。

还有一些通道是在异步Rust之外使用的,比如 std::sync::mpsccrossbeam::channel。这些通道通过阻塞线程来等待消息,这在异步代码中是不允许的。

背压(Backpressure)

背压是一种设计对高负荷反应良好的应用程序的模式。例如,mpsc 通道有有界的和无界的两种形式。通过使用有界通道,如果接收方不能跟上消息的数量,接收方可以对发送方施加 “背压”,这就避免了随着通道上的消息越来越多,内存使用量无限制地增长。

Actor

一种设计应用程序的模式。Actor是指一个独立生成的任务,它代表应用程序的其他部分管理一些资源,使用通道与应用程序的其他部分进行通信。

3 - 资料收集

收集Tokio的各种资料

官方网站

社区

  • TODO

文档