文盘Rust -- 用Tokio实现简易任务池
作者:京东科技 贾世闻
Tokio 无疑是 Rust 世界中最优秀的异步Runtime实现。非阻塞的特性带来了优异的性能,但是在实际的开发中我们往往需要在某些情况下阻塞任务来实现某些功能。
我们看看下面的例子
fn main(){ let max_task = 1; let rt = runtime::Builder::new_multi_thread() .worker_threads(max_task) .build() .unwrap(); rt.block_on(async { println!("tokio_multi_thread "); for i in 0..100 { println!("run {}", i); tokio::spawn(async move { println!("spawn {}", i); thread::sleep(Duration::from_secs(2)); }); } }); }
我们期待的运行结构是通过异步任务打印出99个 “spawn i",但实际输出的结果大概这样
tokio_multi_thread run 0 run 1 run 2 ....... run 16 spawn 0 run 17 ...... run 99 spawn 1 spawn 2 ...... spawn 29 ...... spawn 58 spawn 59
59执行完后面就没有输出了,如果把max_task设置为2,情况会好一点,但是也没有执行完所有的异步操作,也就是说在资源不足的情况下,Tokio会抛弃某些任务,这不符合我们的预期。那么能不能再达到了某一阀值的情况下阻塞一下,不再给Tokio新的任务呢。这有点类似线程池,当达达最大线程数的时候阻塞后面的任务待有释放的线程后再继续。
我们看看下面的代码。
fn main(){ let max_task = 2; let rt = runtime::Builder::new_multi_thread() .worker_threads(max_task) .enable_time() .build() .unwrap(); let mut set = JoinSet::new(); rt.block_on(async { for i in 0..100 { println!("run {}", i); while set.len() >= max_task { set.join_next().await; } set.spawn(async move { sleep().await; println!("spawn {}", i); }); } while set.len() > 0 { set.join_next().await; } }); }
我们使用JoinSet来管理派生出来的任务。set.join_next().await; 保证至少一个任务被执行完成。结合set的len,我们可以在任务达到上限时阻塞任务派生。当循环结束,可能还有未完成的任务,所以只要set.len()大于0就等待任务结束。
输出大概长这样
running 1 test tokio_multi_thread run 0 run 1 spawn 0 run 2 spawn 1 ...... run 31 spawn 30 run 32 spawn 31 run 33 ...... run 96 spawn 95 run 97 spawn 96 run 98 spawn 97 run 99 spawn 98 spawn 99
符合预期,代码不多,有兴趣的同学可以动手尝试一下。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
应用部署引起上游服务抖动问题分析及优化实践方案
作者:京东物流 朱永昌 背景介绍 本文主要围绕应用部署引起上游服务抖动问题展开,结合百川分流系统实例,提供分析、解决思路,并提供一套切实可行的实践方案。 百川分流系统作为交易订单中心的专用网关,为交易订单中心提供统一的对外标准服务(包括接单、修改、取消、回传等),对内则基于配置规则将流量分发到不同业务线的应用上。随着越来越多的流量切入百川系统,因系统部署引起服务抖动导致上游系统调用超时的问题也逐渐凸显出来。为提供稳定的交易服务系统,提升系统可用率,需要对该问题进行优化。 经调研,集团内部现有两种预热方案: (1)JSF官方提供的预热方案; (2)行云编排部署结合录制回放的预热方案。两种方法均无法达到预期效果。 关于方案 (1)首先,使用的前提条件是JSF消费端必需升级JSF版本到1.7.6,百川分流系统上游调用方有几十个,推动所有调用方升级版本比较困难;其次,JSF平台预热规则以接口纬度进行配置,百川分流系统对外提供46个接口,配置复杂;最关键的是该方案的预热规则配置的是在一个固定预热周期(比如1分钟)内某个接口的预热权重(接收调用量比例),简单理解就是小流量试跑,这就决定了该方案无法...
- 下一篇
vivo全球商城:电商交易平台设计
作者:vivo 官网商城开发团队 - Cheng Kun、Liu Wei 本文介绍了交易平台的设计理念和关键技术方案,以及实践过程中的思考与挑战。 点击查阅:《vivo 全球商城》系列文章 一、背景 vivo官方商城经过了七年的迭代,从单体架构逐步演进到微服务架构,我们的开发团队沉淀了许多宝贵的技术与经验,对电商领域业务也有相当深刻的理解。 去年初,团队承接了O2O商城的建设任务,还有即将成立的礼品中台,以及官方商城的线上购买线下门店送货需求,都需要搭建底层的商品、交易和库存能力。 为节约研发与运维成本,避免重复造轮子,我们决定采用平台化的思想来搭建底层系统,以通用能力灵活支撑上层业务的个性化需求。 包括交易平台、商品平台、库存平台、营销平台在内的一整套电商平台化系统应运而生。 本文将介绍交易平台的架构设计理念与实践,以及上线后持续迭代过程中的挑战与思考。 二、整体架构 2.1 架构目标 除了高并发、高性能、高可用这三高外,还希望做到: 低成本注重模型与服务的可重用性,灵活支撑各业务的个性化需求,提高开发效率,降低人力成本。 高扩展 系统架构简单清晰,应用系统间耦合低,容易水平扩展,业...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Hadoop3单机部署,实现最简伪集群
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Windows10,CentOS7,CentOS8安装Nodejs环境
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker安装Oracle12C,快速搭建Oracle学习环境