WebAssembly (Wasm) 正在成為一個(gè)廣受歡迎的編譯目標(biāo),幫助開發(fā)者構(gòu)建可遷移平臺(tái)的應(yīng)用。最近 Greptime 和 WasmEdge 協(xié)作,支持了在 WasmEdge 平臺(tái)上的 Wasm 應(yīng)用通過 MySQL 協(xié)議讀寫 GreptimeDB 中的時(shí)序數(shù)據(jù)。
什么是 WebAssembly
WebAssembly 是一種新的指令格式,同時(shí)具備了跨平臺(tái)和接近原生機(jī)器代碼的執(zhí)行速度。通過將 C/C++ 或 Rust 代碼編譯成 WebAssembly ,可以在瀏覽器中提升程序的性能。而在瀏覽器外的其他運(yùn)行環(huán)境,尤其是 CDN 或 IoT 的邊緣端,我們也可以利用 WebAssembly 實(shí)現(xiàn)沙盒、動(dòng)態(tài)加載的插件機(jī)制等高級(jí)的功能。
什么是 WasmEdge
WasmEdge 是 CNCF 的沙箱項(xiàng)目,提供上文提到的沙盒能力,允許開發(fā)者在 WebAssembly 標(biāo)準(zhǔn)的基礎(chǔ)上,進(jìn)一步擴(kuò)展其能訪問的資源和接口。例如,WasmEdge 為 Wasm 提供了額外的 TLS、網(wǎng)絡(luò)能力和 AI 能力,大大豐富了使用場(chǎng)景。
WasmEdge GitHub 地址:
https://github.com/WasmEdge/WasmEdge
安裝 GreptimeDB 和 WasmEdge
如果你已經(jīng)安裝了 GreptimeDB ,可以跳過這個(gè)步驟。
下載 GreptimeDB 并運(yùn)行:
curl-Lhttps://github.com/GreptimeTeam/greptimedb/raw/develop/scripts/install.sh|sh ./greptimestandalonestart
安裝 WasmEdge:
curl-sSfhttps://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh|bash-s
編寫 GreptimeDB 的 WASM 應(yīng)用
在 WasmEdge 中,我們可以使用 MySQL 協(xié)議,讓 Rust 語言編寫的應(yīng)用程序連接到 GreptimeDB。
首先通過cargo new創(chuàng)建一個(gè)新的 Rust 項(xiàng)目,我們的編譯目標(biāo)將是wasm32-wasi,可以在項(xiàng)目根目錄下創(chuàng)建.cargo/config.toml文件,指定默認(rèn)編譯目標(biāo),之后就無需在每次cargo build命令后專門指定--target了。
#.cargo/config.toml [build] target="wasm32-wasi"
編輯Cargo.toml增加依賴。mysql_async的應(yīng)用需要tokio運(yùn)行時(shí),WasmEdge 維護(hù)了這兩個(gè)庫的修改版本,使他們能夠編譯成 WebAssembly 代碼,并且運(yùn)行到 WasmEdge 環(huán)境中。
[package] name="greptimedb" version="0.1.0" edition="2021" [dependencies] mysql_async_wasi="0.31" time="0.3" tokio_wasi={version="1",features=["io-util","fs","net","time","rt","macros"]}
進(jìn)一步編輯src/main.rs文件,加入數(shù)據(jù)庫訪問的邏輯。這段代碼將演示:
通過環(huán)境變量讀取數(shù)據(jù)庫地址,并創(chuàng)建連接池;
執(zhí)行 SQL 語句創(chuàng)建數(shù)據(jù)表;
插入數(shù)據(jù);
查詢數(shù)據(jù)。
定義數(shù)據(jù)結(jié)構(gòu):
#[derive(Debug)] structCpuMetric{ hostname:String, environment:String, usage_user:f64, usage_system:f64, usage_idle:f64, ts:i64, } implCpuMetric{ fnnew( hostname:String, environment:String, usage_user:f64, usage_system:f64, usage_idle:f64, ts:i64, )->Self{ Self{ hostname, environment, usage_user, usage_system, usage_idle, ts, } }
}
初始化數(shù)據(jù)庫連接池:
usemysql_async::{ prelude::*,Opts,OptsBuilder,Pool,PoolConstraints,PoolOpts,Result, }; usetime::PrimitiveDateTime; fnget_url()->String{ ifletOk(url)=std::var("DATABASE_URL"){ letopts=Opts::from_url(&url).expect("DATABASE_URLinvalid"); ifopts .db_name() .expect("adatabasenameisrequired") .is_empty() { panic!("databasenameisempty"); } url }else{ "mysql://root:pass@127.0.0.1:3306/mysql".into() } } #[tokio::main(flavor="current_thread")] asyncfnmain()->Result<()>{ //Alternative:The"easy"waywithadefaultconnectionpool //letpool=Pool::from_url(&*get_url()).unwrap()); //letmutconn=pool.get_conn().await.unwrap(); //Belowwecreateacustomizedconnectionpool letopts=Opts::from_url(&*get_url()).unwrap(); letbuilder=OptsBuilder::from_opts(opts); //Theconnectionpoolwillhaveaminof1andmaxof2connections. letconstraints=PoolConstraints::new(1,2).unwrap(); letpool_opts=PoolOpts::default().with_constraints(constraints); letpool=Pool::new(builder.pool_opts(pool_opts)); letmutconn=pool.get_conn().await.unwrap(); Ok(()) }
創(chuàng)建數(shù)據(jù)表:
//Createtableifnotexists r"CREATETABLEIFNOTEXISTSwasmedge_example_cpu_metrics( hostnameSTRING, environmentSTRING, usage_userDOUBLE, usage_systemDOUBLE, usage_idleDOUBLE, tsTIMESTAMP, TIMEINDEX(ts), PRIMARYKEY(hostname,environment) );" .ignore(&mutconn) .await?;
插入數(shù)據(jù):
letmetrics=vec![ CpuMetric::new( "host0".into(), "test".into(), 32f64, 3f64, 4f64, 1680307200050, ), CpuMetric::new( "host1".into(), "test".into(), 29f64, 32f64, 50f64, 1680307200050, ), CpuMetric::new( "host0".into(), "test".into(), 32f64, 3f64, 4f64, 1680307260050, ), CpuMetric::new( "host1".into(), "test".into(), 29f64, 32f64, 50f64, 1680307260050, ), CpuMetric::new( "host0".into(), "test".into(), 32f64, 3f64, 4f64, 1680307320050, ), CpuMetric::new( "host1".into(), "test".into(), 29f64, 32f64, 50f64, 1680307320050, ), ]; r"INSERTINTOwasmedge_example_cpu_metrics(hostname,environment,usage_user,usage_system,usage_idle,ts) VALUES(:hostname,:environment,:usage_user,:usage_system,:usage_idle,:ts)" .with(metrics.iter().map(|metric|{ params!{ "hostname"=>&metric.hostname, "environment"=>&metric.environment, "usage_user"=>metric.usage_user, "usage_system"=>metric.usage_system, "usage_idle"=>metric.usage_idle, "ts"=>metric.ts, } })) .batch(&mutconn)
.await?;
查詢數(shù)據(jù):
letloaded_metrics="SELECT*FROMwasmedge_example_cpu_metrics" .with(()) .map( &mutconn, |(hostname,environment,usage_user,usage_system,usage_idle,raw_ts):( String, String, f64, f64, f64, PrimitiveDateTime, )|{ letts=raw_ts.assume_utc().unix_timestamp()*1000; CpuMetric::new( hostname, environment, usage_user, usage_system, usage_idle, ts, ) }, ) .await?;
println!("{:?}",loaded_metrics);
WasmEdge 團(tuán)隊(duì)提供的tokio和mysql_async庫與原始版本編程接口完全一致,因此可以無縫地將普通 Rust 應(yīng)用切換到 WebAssembly 平臺(tái)上。
編譯這個(gè)項(xiàng)目,我們可以獲得 greptimedb.wasm 文件:
cargobuild ls-lhtarget/wasm32-wasi/debug/greptimedb.wasm
通過 WasmEdge 運(yùn)行我們的程序:
wasmedge--env"DATABASE_URL=mysql://localhost:4002/public"target/wasm32-wasi/debug/greptimedb.wasm
上面這段示例程序已經(jīng)納入了 WasmEdge 的數(shù)據(jù)庫使用示例,你可以在 GitHub 倉(cāng)庫找到完整的代碼:
https://github.com/WasmEdge/wasmedge-db-examples/tree/main/greptimedb。
總結(jié)
WasmEdge 為 WebAssembly 應(yīng)用提供了更多的擴(kuò)展能力。如果你也將應(yīng)用部署在 WebAssembly 環(huán)境里,未來我們還可以使用 OpenTelemetry SDK 采集指標(biāo)數(shù)據(jù)直接存儲(chǔ)到 GreptimeDB 。現(xiàn)在就下載 GreptimeDB 或開通 GreptimeCloud 實(shí)例運(yùn)行上面的例子吧。
審核編輯:湯梓紅
-
時(shí)序
+關(guān)注
關(guān)注
5文章
392瀏覽量
37427 -
MySQL
+關(guān)注
關(guān)注
1文章
829瀏覽量
26741 -
編譯
+關(guān)注
關(guān)注
0文章
661瀏覽量
33040 -
GitHub
+關(guān)注
關(guān)注
3文章
473瀏覽量
16564 -
Rust
+關(guān)注
關(guān)注
1文章
230瀏覽量
6664
原文標(biāo)題:從 WasmEdge 運(yùn)行環(huán)境讀寫 Rust Wasm 應(yīng)用的時(shí)序數(shù)據(jù)
文章出處:【微信號(hào):Rust語言中文社區(qū),微信公眾號(hào):Rust語言中文社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論