2021年上半年,撸了个rust cli开发的框架,基本上把交互模式,子命令提醒这些cli该有的罕用性能做进去了。我的项目地址:https://github.com/jiashiwen/interactcli-rs。
春节以前看到axum曾经0.4.x了,于是想看看能不能用rust做个服务端的框架。
春节后开始入手,在做的过程中会碰到各种乏味的问题。于是记下来想和社区的小伙伴一起分享。社区里的小伙伴大部分是DBA和运维同学,如果想进一步理解更底层的货色,代码动手是个好路数。
我集体认为想看懂代码先要写好代码,起码理解开发的根本路数和工程的个别组织模式。但好多同学的次要工作并不是专职开发,所以也就没有机会下探研发技术。代码这个事儿光看书是不论用的。理解一门语言最好的形式是应用它。
那么,问题来了非研发人员如何相熟语言呢?咏春拳里有句拳谚:”无师无对手,桩与镜中求“。解释两句,就是在没有师兄弟练习的状况下,对着镜子和木人桩练习。在这里我感觉所谓桩有两层含意,一个是木人桩,就是练习的工具,一个是”站桩“,传统武术训练基本功的办法。其实在理论的工作中DBA和运维同学会有很多场景须要编程,比方做一些运维方面的统计工作;剖析问题时须要拿到某些数据。如果谋求简略用Python的话可能对于其余语言就没有涉猎了。如果联合你运维数据库的原生开发语言,假以时日缓缓就能看懂相干的底层逻辑了。我集体有个观点,产品研发的原生语言是理解产品底层最好的入口。
前面如果在Rust的开发过程中有其余问题,我自己会把问题结合实际也写到这个系列里,也心愿社区里对Rust感兴趣的小伙伴一起来”盘Rust“。 言归正传,说说这次在玩儿Rust时遇到的问题吧。
在 Rust 开发过程中,咱们常常须要全局变量作为公共数据的寄存地位。通常做法是利用 lazy_static/onecell 和 mux/rwlock 生成一个动态的 collection。
代码长这样
use std::collections::HashMap;use std::sync::RwLock;lazy_static::lazy_static! { static ref GLOBAL_MAP: RwLock<HashMap<String,String>> = RwLock::new({ let map = HashMap::new(); map });}
根本的数据存取这样实现
use std::collections::HashMap;use std::sync::RwLock;lazy_static::lazy_static! { static ref GLOBAL_MAP: RwLock<HashMap<String,String>> = RwLock::new({ let map = HashMap::new(); map });}fn main() { for i in 0..3 { insert_global_map(i.to_string(), i.to_string()) } print_global_map(); println!("finished!");}fn insert_global_map(k: String, v: String) { let mut gpw = GLOBAL_MAP.write().unwrap(); gpw.insert(k, v);}fn print_global_map() { let gpr = GLOBAL_MAP.read().unwrap(); for pair in gpr.iter() { println!("{:?}", pair); }}
insert\_global\_map函数用来向GLOBAL\_MAP插入数据,print\_global_map()用来读取数据,下面程序的运行后果如下
("0", "0")("1", "1")("2", "2")
上面咱们来实现一个比较复杂一点儿的需要,从 GLOBAL_MAP 里取一个数,如果存在前面进行删除操作,直觉通知咱们代码仿佛应该这样写
use std::collections::HashMap;use std::sync::RwLock;lazy_static::lazy_static! { static ref GLOBAL_MAP: RwLock<HashMap<String,String>> = RwLock::new({ let map = HashMap::new(); map });}fn main() { for i in 0..3 { insert_global_map(i.to_string(), i.to_string()) } print_global_map(); get_and_remove(1.to_string()); println!("finished!");}fn insert_global_map(k: String, v: String) { let mut gpw = GLOBAL_MAP.write().unwrap(); gpw.insert(k, v);}fn print_global_map() { let gpr = GLOBAL_MAP.read().unwrap(); for pair in gpr.iter() { println!("{:?}", pair); }}fn get_and_remove(k: String) { println!("execute get_and_remove"); let gpr = GLOBAL_MAP.read().unwrap(); let v = gpr.get(&*k.clone()); let mut gpw = GLOBAL_MAP.write().unwrap(); gpw.remove(&*k.clone());}
下面这段代码输入长这样
("0", "0")("1", "1")("2", "2")execute get_and_remove
代码没有完结,而是hang在了get\_and\_remove函数。 为啥会呈现这样的状况呢?这兴许与生命周期无关。gpr和gpw 这两个返回值别离为 RwLockReadGuard 和 RwLockWriteGuard,查看这两个
struct 发现的确可能引起死锁
must_not_suspend = "holding a RwLockWriteGuard across suspend \ points can cause deadlocks, delays, \ and cause Future's to not implement `Send`"
问题找到了就能够着手解决办法了,既然是与rust的生命周期无关,那是不是能够把读和写别离放在两个不同的生命周期里呢,于是对代码进行改写
use std::collections::HashMap;use std::sync::RwLock;lazy_static::lazy_static! { static ref GLOBAL_MAP: RwLock<HashMap<String,String>> = RwLock::new({ let map = HashMap::new(); map });}fn main() { for i in 0..3 { insert_global_map(i.to_string(), i.to_string()) } print_global_map(); get_and_remove(1); println!("finished!");}fn insert_global_map(k: String, v: String) { let mut gpw = GLOBAL_MAP.write().unwrap(); gpw.insert(k, v);}fn print_global_map() { let gpr = GLOBAL_MAP.read().unwrap(); for pair in gpr.iter() { println!("{:?}", pair); }}fn get_and_remove_deadlock(k: String) { println!("execute get_and_remove"); let gpr = GLOBAL_MAP.read().unwrap(); let _v = gpr.get(&*k.clone()); let mut gpw = GLOBAL_MAP.write().unwrap(); gpw.remove(&*k.clone());}fn get_and_remove(k: i32) { let v = { let gpr = GLOBAL_MAP.read().unwrap(); let v = gpr.get(&*k.to_string().clone()); match v { None => Err(anyhow!("")), Some(pair) => Ok(pair.to_string().clone()), } }; let vstr = v.unwrap(); println!("get value is {:?}", vstr.clone()); let mut gpw = GLOBAL_MAP.write().unwrap(); gpw.remove(&*vstr);}
正确输入
("1", "1")("0", "0")("2", "2")get value is "1"("0", "0")("2", "2")finished!
Rust的生命周期是个很有意思的概念,从意识到了解的确有个过程。
源码地址
作者:京东科技 贾世闻
起源:京东云开发者社区 转载请注明起源