From 46ad5979786281e8c1d2d41a3e5290cb17699a3b Mon Sep 17 00:00:00 2001 From: sunface Date: Mon, 11 Apr 2022 13:00:53 +0800 Subject: [PATCH] update async and tokio --- src/SUMMARY.md | 2 +- src/async-rust/async/getting-started.md | 7 +++++++ src/async-rust/tokio/overview.md | 8 ++++++++ src/logs/observe/about-observe.md | 2 +- src/logs/observe/trace.md | 1 + 5 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/logs/observe/trace.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 58884d90..263b916f 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -180,7 +180,7 @@ - [自定义 tracing 的输出格式](logs/tracing-logger.md) - [监控](logs/observe/intro.md) - [可观测性](logs/observe/about-observe.md) - + - [分布式追踪](logs/observe/trace.md) - [Rust 最佳实践](practice/intro.md) - [日常开发三方库精选](practice/third-party-libs.md) - [命名规范](practice/naming.md) diff --git a/src/async-rust/async/getting-started.md b/src/async-rust/async/getting-started.md index 21c2fa3e..57c0b9e3 100644 --- a/src/async-rust/async/getting-started.md +++ b/src/async-rust/async/getting-started.md @@ -54,6 +54,13 @@ 总之,`async`编程并没有比多线程更好,最终还是根据你的使用场景作出合适的选择,如果无需高并发,或者也不在意线程切换带来的性能损耗,那么多线程使用起来会简单、方便的多!最后再简单总结下: +> 若大家使用 tokio,那 CPU 密集的任务尤其需要用线程的方式去处理,例如使用 `spawn_blocking` 创建一个阻塞的线程取完成相应 CPU 密集任务。 +> +> 至于具体的原因,不仅是上文说到的那些,还有一个是:tokio 是协作式地调度器,如果某个 CPU 密集的异步任务是通过 tokio 创建的,那理论上来说,该异步任务需要跟其它的异步任务交错执行,最终大家都得到了执行,皆大欢喜。但实际情况是,CPU 密集的任务很可能会一直霸着着 CPU,此时 tokio 的调度方式决定了该任务会一直被执行,这意味着,其它的异步任务无法得到执行的机会,最终这些任务都会因为得不到资源而饿死。 +> +> 而使用 `spawn_blocking` 后,会创建一个单独的 OS 线程,该线程并不会被 tokio 所调度( 被 OS 所调度 ),因此它所执行的 CPU 密集任务也不会导致 tokio 调度的那些异步任务被饿死 + + - 有大量 `IO` 任务需要并发运行时,选 `async` 模型 - 有部分 `IO` 任务需要并发运行时,选多线程,如果想要降低线程创建和销毁的开销,可以使用线程池 - 有大量 `CPU` 密集任务需要并行运行时,例如并行计算,选多线程模型,且让线程数等于或者稍大于 `CPU` 核心数 diff --git a/src/async-rust/tokio/overview.md b/src/async-rust/tokio/overview.md index f21e194c..787220ee 100644 --- a/src/async-rust/tokio/overview.md +++ b/src/async-rust/tokio/overview.md @@ -76,6 +76,14 @@ Rust 语言的安全可靠性顺理成章的影响了 `tokio` 的可靠性,曾 - 读取大量的文件, 读取文件的瓶颈主要在于操作系统,因为 OS 没有提供异步文件读取接口,大量的并发并不会提升文件读取的并行性能,反而可能会造成不可忽视的性能损耗,因此建议使用线程(或线程池)的方式 - 发送 HTTP 请求,`tokio` 的优势是给予你并发处理大量任务的能力,对于这种轻量级 HTTP 请求场景,`tokio` 除了增加你的代码复杂性,并无法带来什么额外的优势。因此,对于这种场景,你可以使用 [`reqwest`](https://github.com/seanmonstar/reqwest) 库,它会更加简单易用。 + +> 若大家使用 tokio,那 CPU 密集的任务尤其需要用线程的方式去处理,例如使用 `spawn_blocking` 创建一个阻塞的线程取完成相应 CPU 密集任务。 +> +> 原因是:tokio 是协作式地调度器,如果某个 CPU 密集的异步任务是通过 tokio 创建的,那理论上来说,该异步任务需要跟其它的异步任务交错执行,最终大家都得到了执行,皆大欢喜。但实际情况是,CPU 密集的任务很可能会一直霸着着 CPU,此时 tokio 的调度方式决定了该任务会一直被执行,这意味着,其它的异步任务无法得到执行的机会,最终这些任务都会因为得不到资源而饿死。 +> +> 而使用 `spawn_blocking` 后,会创建一个单独的 OS 线程,该线程并不会被 tokio 所调度( 被 OS 所调度 ),因此它所执行的 CPU 密集任务也不会导致 tokio 调度的那些异步任务被饿死 + + ## 总结 离开三方开源社区提供的异步运行时, `async/await` 什么都不是,甚至还不如一堆破铜烂铁,除非你选择根据自己的需求手撸一个。 diff --git a/src/logs/observe/about-observe.md b/src/logs/observe/about-observe.md index 05dabfd0..5401e805 100644 --- a/src/logs/observe/about-observe.md +++ b/src/logs/observe/about-observe.md @@ -73,7 +73,7 @@ 再说了,`grafana` 的 UI 做的好看啊,没人能拒绝美好的事物吧 :D -好了,一篇口水文终于结束了,在后续章节我们将学习如何使用 `OpenTelemetry + Jaeger + Prometheus + Grafana` 搭建一套可用的监控服务,先来看看分布式追踪和 `OpenTelemetry`。 +好了,一篇口水文终于结束了,在后续章节我们将学习如何使用 `OpenTelemetry + Jaeger + Prometheus + Grafana` 搭建一套可用的监控服务,先来看看如何搭建和使用分布式追踪监控。 > "tracing 呢?你这个监控服务怎么没有它的身影,日志章节口口声声的爱,现在就忘记了吗?" > diff --git a/src/logs/observe/trace.md b/src/logs/observe/trace.md new file mode 100644 index 00000000..d27dd3f3 --- /dev/null +++ b/src/logs/observe/trace.md @@ -0,0 +1 @@ +# 分布式追踪