从 WasmEdge 运行环境读写 Rust Wasm 应用的时序数据
WebAssembly (Wasm) 正在成为一个广受欢迎的编译目标,帮助开发者构建可迁移平台的应用。最近 Greptime 和 WasmEdge 协作,支持了在 WasmEdge 平台上的 Wasm 应用通过 MySQL 协议读写 GreptimeDB 中的时序数据。
什么是 WebAssembly
WebAssembly 是一种新的指令格式,同时具备了跨平台和接近原生机器代码的执行速度。** 通过将 C/C++ 或 Rust 代码编译成 WebAssembly ,可以在浏览器中提升程序的性能。而在浏览器外的其他运行环境,尤其是 CDN 或 IoT 的边缘端,我们也可以利用 WebAssembly 实现沙盒、动态加载的插件机制等高级的功能。
什么是 WasmEdge
WasmEdge 是 CNCF 的沙箱项目,提供上文提到的沙盒能力,允许开发者在 WebAssembly 标准的基础上,进一步扩展其能访问的资源和接口。例如,WasmEdge 为 Wasm 提供了额外的 TLS、网络能力和 AI 能力,大大丰富了使用场景。
WasmEdge GitHub 地址:
https://github.com/WasmEdge/WasmEdge
安装 GreptimeDB 和 WasmEdge
如果你已经安装了 GreptimeDB ,可以跳过这个步骤。
下载 GreptimeDB 并运行:
curl -L https://github.com/GreptimeTeam/greptimedb/raw/develop/scripts/install.sh | sh
./greptime standalone start
安装 WasmEdge:
curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash -s
编写 GreptimeDB 的 WASM 应用
在 WasmEdge 中,我们可以使用 MySQL 协议,让 Rust 语言编写的应用程序连接到 GreptimeDB。
首先通过 `cargo new` 创建一个新的 Rust 项目,我们的编译目标将是 `wasm32-wasi`,可以在项目根目录下创建 `.cargo/config.toml` 文件,指定默认编译目标,之后就无需在每次 `cargo build` 命令后专门指定 `--target` 了。
# .cargo/config.toml
[build]
target = "wasm32-wasi"
编辑 `Cargo.toml` 增加依赖。`mysql_async` 的应用需要 `tokio` 运行时,WasmEdge 维护了这两个库的修改版本,使他们能够编译成 WebAssembly 代码,并且运行到 WasmEdge 环境中。
[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"] }
进一步编辑 `src/main.rs` 文件,加入数据库访问的逻辑。这段代码将演示:
1. 通过环境变量读取数据库地址,并创建连接池;
2. 执行 SQL 语句创建数据表;
3. 插入数据;
4. 查询数据。
定义数据结构:
#[derive(Debug)]
struct CpuMetric {hostname: String,environment: String,usage_user: f64,usage_system: f64,usage_idle: f64,ts: i64,
}impl CpuMetric {fn new(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,}}
}
初始化数据库连接池:
use mysql_async::{prelude::*, Opts, OptsBuilder, Pool, PoolConstraints, PoolOpts, Result,
};
use time::PrimitiveDateTime;fn get_url() -> String {if let Ok(url) = std::env::var("DATABASE_URL") {let opts = Opts::from_url(&url).expect("DATABASE_URL invalid");if opts.db_name().expect("a database name is required").is_empty(){panic!("database name is empty");}url} else {"mysql://root:pass@127.0.0.1:3306/mysql".into()}
}#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {// Alternative: The "easy" way with a default connection pool// let pool = Pool::new(Opts::from_url(&*get_url()).unwrap());// let mut conn = pool.get_conn().await.unwrap();// Below we create a customized connection poollet opts = Opts::from_url(&*get_url()).unwrap();let builder = OptsBuilder::from_opts(opts);// The connection pool will have a min of 1 and max of 2 connections.let constraints = PoolConstraints::new(1, 2).unwrap();let pool_opts = PoolOpts::default().with_constraints(constraints);let pool = Pool::new(builder.pool_opts(pool_opts));let mut conn = pool.get_conn().await.unwrap();Ok(())
}
创建数据表:
// Create table if not existsr"CREATE TABLE IF NOT EXISTS wasmedge_example_cpu_metrics (hostname STRING,environment STRING,usage_user DOUBLE,usage_system DOUBLE,usage_idle DOUBLE,ts TIMESTAMP,TIME INDEX(ts),PRIMARY KEY(hostname, environment)
);".ignore(&mut conn).await?;
插入数据:
let metrics = 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"INSERT INTO wasmedge_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(&mut conn).await?;
查询数据:
let loaded_metrics = "SELECT * FROM wasmedge_example_cpu_metrics".with(()).map(&mut conn,|(hostname, environment, usage_user, usage_system, usage_idle, raw_ts): (String,String,f64,f64,f64,PrimitiveDateTime,)| {let ts = raw_ts.assume_utc().unix_timestamp() * 1000;CpuMetric::new(hostname,environment,usage_user,usage_system,usage_idle,ts,)},).await?;println!("{:?}", loaded_metrics);
WasmEdge 团队提供的 `tokio` 和 `mysql_async` 库与原始版本编程接口完全一致,因此可以无缝地将普通 Rust 应用切换到 WebAssembly 平台上。
编译这个项目,我们可以获得 greptimedb.wasm 文件:
cargo build
ls -lh target/wasm32-wasi/debug/greptimedb.wasm
通过 WasmEdge 运行我们的程序:
wasmedge --env "DATABASE_URL=mysql://localhost:4002/public" target/wasm32-wasi/debug/greptimedb.wasm
上面这段示例程序已经纳入了 WasmEdge 的数据库使用示例,你可以在 GitHub 仓库找到完整的代码:
https://github.com/WasmEdge/wasmedge-db-examples/tree/main/greptimedb。
总结
WasmEdge 为 WebAssembly 应用提供了更多的扩展能力。如果你也将应用部署在 WebAssembly 环境里,未来我们还可以使用 OpenTelemetry SDK 采集指标数据直接存储到 GreptimeDB 。现在就下载 GreptimeDB 或开通 GreptimeCloud 实例运行上面的例子吧。
相关文章:
从 WasmEdge 运行环境读写 Rust Wasm 应用的时序数据
WebAssembly (Wasm) 正在成为一个广受欢迎的编译目标,帮助开发者构建可迁移平台的应用。最近 Greptime 和 WasmEdge 协作,支持了在 WasmEdge 平台上的 Wasm 应用通过 MySQL 协议读写 GreptimeDB 中的时序数据。 什么是 WebAssembly WebAssembly 是一种…...

算法训练营Day34(贪心算法)
1005.K次取反后最大化的数组和 1005. K 次取反后最大化的数组和 - 力扣(LeetCode) 秒了 class Solution {public int largestSumAfterKNegations(int[] nums, int k) {Arrays.sort(nums);// -4 -3 -2 -1 5//-2 -2 0 2 5int last -1;for(int i 0;i<…...

uniapp:全局消息是推送,实现app在线更新,WebSocket,apk上传
全局消息是推送,实现app在线更新,WebSocket 1.在main.js中定义全局的WebSocket2.java后端建立和发送WebSocket3.通知所有用户更新 背景: 开发人员开发后app后打包成.apk文件,上传后通知厂区在线用户更新app。 那么没在线的怎么办&…...

ARM1.2作业
实现数码管不同位显示不同的数字 spi.h #ifndef __SPI_H__ #define __SPI_H__ #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h"//MOSI对应的引脚输入高低电平的信号PE14 #define MOSI_OUTPUT_H() do{GPIOE->ODR | (0x1 << 14);}whi…...
【算法专题】递归算法
递归 递归1. 汉诺塔问题2. 合并两个有序链表3. 反转链表4. 两两交换链表中的节点5. Pow(x, n) --- 快速幂 递归 在解决⼀个规模为 n 的问题时,如果满足以下条件,我们可以使用递归来解决: 问题可以被划分为规模更小的子问题,并且…...
不停止业务的情况下优化 Elasticsearch Reindex
在使用 Elasticsearch 时,我们总有需要修改索引映射的时候,这时我们只能进行 _reindex。事实上,这是一个相当昂贵的操作,因为根据数据量和分片数量,完整复制一个索引可能需要几个小时。 花费的时间不是大问题,但更严重的是,它会影响生产环境的性能甚至功能。 相信大家…...
PB 按Excel动态创建对应字段
/* > Function: w_cwjk_xhyy.wf_dw_init >-------------------------------------------------------------------- > 描述: 按excel表格列名,创建对应字段,用于部分接口对应字段导出文件 >-------------------------------------------------------------------- …...

数据结构——红黑树 and B-树
红黑树 根据平衡条件第4、5两点 最短路径,都是黑色 最长路径,红黑相间 最长是最短的两倍 B-树...
Android中线程间的通信-Handler
Handler机制在Android中主要用于线程间的通信,特别是处理从子线程向主线程(UI线程)传递消息和更新界面。 Handler中的四个关键对象及其作用: Message: Message 是在线程间传递的数据载体,它包含了需要处理…...

Spring Boot Admin健康检查引起的Spring Boot服务假死
问题现象 最近在spring boot项目中引入了 spring-boot-starter-actuator 后,测试环境开始出现服务假死的现象, 且这个问题十分怪异,只在多个微服务中的简称A的这个服务中出现,其他服务都没有出现这个问题, 之所以说…...

java企业人事信息管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 java Web企业人事信息管理系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境 为TOMCAT7.0,Myeclipse8.5开发,数据库为M…...
如何通过 useMemo 和 useCallback 提升你的 React 应用性能
背景 在 React 中,useMemo 和 useCallback 这两个 hook 是我们优化应用性能的有力工具。它们会返回 memoized 版本的值或函数,只在依赖项发生变化时才进行重新计算或定义。 Hook 介绍 useMemo useMemo 的作用是返回一个 memoized 值,它接…...

ArkTS - @Prop、@Link
一、作用 Prop 装饰器 和Link装饰器都是父组件向子组件传递参数,子组件接收父组件参数的时候用的,变量前边需要加上Prop或者Link装饰器即可。(跟前端vue中父组件向子组件传递参数类似) // 子组件 Component struct SonCom {Prop…...

Python中matplotlib库的使用1
1 matplotlib库简介 matplotlib是一个数学绘图库,可以将数据通过图形的方式显示出来,也就是数据可视化。 2 matplotlib库的安装 2.1 打开cmd窗口 点击键盘的“Win”“R”键,在弹出的“运行”对话框的“打开”栏中输入“cmd”,…...
位乘积计数-蓝桥
题目链接:1.位乘积计数 - 蓝桥云课 (lanqiao.cn) 解题思路:10的5次数量级暴力居然过了,看来测试样例很水,直接1遍历到n,再用一个循环判断每位数相乘乘机是否等于m即可。 下面是c代码: #include <iost…...

HCIA-Datacom题库(自己整理分类的)——OSPF协议判断
1.路由表中某条路由信息的Proto为OSPF则此路由的优先级一定为10。√ 2.如果网络管理员没有配置骨干区域,则路由器会自动创建骨干区域? 路由表中某条路由信息的Proto为OSPF,则此路由的优先级一定为10。 当两台OSPF路由器形成2-WAY邻居关系时࿰…...

【FPGA/verilog -入门学习16】fpga状态机实现
需求: 用两段式状态机设计序列码检测机。这个序列码检测机用于检索连续输入的 1bit 数据 (每个时钟周期输入 1bit),当检测到一串“101100”的输入数据时,产生一个时钟周期的 高脉冲指示信号 状态图 //实现状态机切…...

记chrome的hackbar无法post php://input的问题
尽管hackbar支持post请求体,但是当请求体里面没有等于号的时候,无法post出去,这样如果需要使用php://input绕过waf的时候就没法做。 在开发人员工具的网络里面可以看到不使用等于号的情况下没有荷载。 之后在这里看到了解决方法,…...
相机解析驱动小记
用过了几款相机,对使用相机也有了一点心得,在此记录。 当你得到一款相机,你需要做的: 第一件事:在datasheet中阅读配置单,知道怎么配置、配置完输出来是什么。 配置输出尺寸;传输模式…...
EasyExcel判断导入时是否符合给定模板
问题描述 在做系统的导入导出模块时需要在导入时判断用户导入的表格是否符合给定的模板,该系统导入导出使用的是EasyExcel,因此在实现该功能时是基于EasyExcel的 解决方案 创建Spring Boot项目,并添加如下依赖 <dependency><group…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...