WebAssembly + Dapr = 下一代云原生运行时?(1)

$ dapr init

⌛ Making the jump to hyperspace…

✅ Downloading binaries and setting up components…

✅ Downloaded binaries and completed components set up.

ℹ️ daprd binary has been installed to /Users/yili/.dapr/bin.

ℹ️ dapr_placement container is running.

ℹ️ dapr_redis container is running.

ℹ️ dapr_zipkin container is running.

ℹ️ Use docker ps to check running containers.

✅ Success! Dapr is up and running. To get started, go here: https://aka.ms/dapr-getting-started

$ dapr run --app-id myapp --dapr-http-port 3500

WARNING: no application command found.

ℹ️ Starting Dapr with id myapp. HTTP Port: 3500. gRPC Port: 63734

ℹ️ Checking if Dapr sidecar is listening on HTTP port 3500

ℹ️ Checking if Dapr sidecar is listening on GRPC port 63734

ℹ️ Dapr sidecar is up and running.

✅ You’re up and running! Dapr logs will appear here.

2. 利用 Redis 作为 WASI 应用的状态存储


我们下面利用 Dapr 的 Get Started 的例子,利用 Redis 作为 WASI 应用的状态存储。具体逻辑如下图。

5.png

注:下面的应用需要 Rust 和 AssemblyScript 环境配置,请大家自行完成。

我们在 Radu 项目的基础上 fork 了一个版本,首先来下载代码,并进行构建。

$ git clone https://github.com/denverdino/wasi-experimental-http

$ cd wasi-experimental-http

$ cargo build

Finished dev [unoptimized + debuginfo] target(s) in 3m 02s

我们利用 AssemblyScript 来实现了这个测试应用,测试代码如下:

$ cat tests/dapr/index.ts

// @ts-ignore

import { Console } from “as-wasi”;

import { DaprClient, StateItem } from “./dapr”;

import { JSON } from “assemblyscript-json”;

Console.log(“Testing Dapr API …”)

let dapr = new DaprClient()

dapr.saveState(“statestore”, “weapon”, JSON.Value.String(“Death Star”))

let o = JSON.Value.Object()

o.set(“name”, “Tatooine”)

o.set(“test”, 123)

let item = new StateItem(“planets”, o)

let items: StateItem[] = [item]

dapr.saveBulkState(“statestore”, items)

let testObj = dapr.getState(“statestore”, “planets”)

let testStr = dapr.getState(“statestore”, “weapon”)

if (testStr.toString() == “Death Star” && testObj.isObj && (<JSON.Integer>(<JSON.Obj>testObj).getInteger(“test”)).valueOf() == 123) {

Console.log(“Test successfully!”)

} else {

Console.log(“Test failed!”)

}

代码逻辑非常简单,就是创建一个 Dapr 客户端,然后通过 REST API,进行 Dapr 的状态管理。我们可以快速验证一下。

$ cargo run

Finished dev [unoptimized + debuginfo] target(s) in 0.19s

Running target/debug/wasi-experimental-http-wasmtime-sample

Testing Dapr API …

POST http://127.0.0.1:3500/v1.0/state/statestore with [{“key”:“weapon”,“value”:“Death Star”}]

POST http://127.0.0.1:3500/v1.0/state/statestore with [{“key”:“planets”,“value”:{“name”:“Tatooine”,“test”:123}}]

GET http://127.0.0.1:3500/v1.0/state/statestore/planets

GET http://127.0.0.1:3500/v1.0/state/statestore/weapon

Test successfully!

module instantiation time: 333.16637ms

3. 关键要点分析


wasi-experimental-http 项目在 Wasmtime (来自 Bytecode Alliance 的一个 WASM 实现)虚拟机上实现了扩展,支持在 WASI 应用中,访问 HTTP 服务。它还提供了一个 AssemblyScript 的 HTTP Client 实现。

wasi-experimental-http 项目:https://github.com/deislabs/wasi-experimental-http/

在此之上,我们为 AssemblyScript 提供一个 Dapr 的封装,可以参见:https://github.com/denverdino/wasi-experimental-http/blob/main/tests/dapr/dapr.ts

// @ts-ignore

import { Console } from “as-wasi”;

import { Method, RequestBuilder, Response } from “…/…/crates/as”;

import { JSONEncoder, JSON } from “assemblyscript-json”;

export class StateItem {

key: string

value: JSON.Value

etag: string | null

metadata: Map<string, string> | null

constructor(key: string, value: JSON.Value) {

this.key = key

this.value = value

this.etag = null

this.metadata = null

}

}

export class DaprClient {

port: i32

address: string

constructor() {

this.address = “127.0.0.1”

this.port = 3500

}

stateURL(storeName: string): string {

return “http://” + this.address + “:” + this.port.toString() + “/v1.0/state/” + storeName

}

saveState(storeName: string, key: string, value: JSON.Value): boolean {

let item = new StateItem(key, value)

let items: StateItem[] = [item]

return this.saveBulkState(storeName, items)

}

saveBulkState(storeName: string, items: StateItem[]): boolean {

// Handle field

let encoder = new JSONEncoder();

// Construct necessary object

encoder.pushArray(null);

for (let i = 0, len = items.length; i < len; i++) {

let item = items[i]

encoder.pushObject(null);

encoder.setString(“key”, item.key)

encodeValue(encoder, “value”, item.value)

if (item.etag != null) {

encoder.setString(“etag”, item.etag)

}

encoder.popObject()

};

encoder.popArray();

// Or get serialized data as string

let jsonString = encoder.toString();

let url = this.stateURL(storeName);

Console.log("POST " + url + " with " + jsonString);

let res = new RequestBuilder(url)

.method(Method.POST)

.header(“Content-Type”, “application/json”)

.body(String.UTF8.encode(jsonString))

.send();

let ok = res.status.toString() == “200”

res.close();

return ok

}

getState(storeName: string, key: string): JSON.Value {

let url = this.stateURL(storeName) + “/” + key;

Console.log("GET " + url);

let res = new RequestBuilder(url)

.method(Method.GET)

.send();

let ok = res.status.toString() == “200”

let result = <JSON.Value> new JSON.Null()

if (ok) {

let body = res.bodyReadAll();

result = <JSON.Value>JSON.parse(body)

}

res.close();

return result

}

};

测试应用的 main 函数,会创建一个 Wasmtime 运行时环境,并为其添加为 HTTP 扩展,并加载执行测试应用的 WASM 字节码:https://github.com/denverdino/wasi-experimental-http/blob/main/src/main.rs

fn main() {

let allowed_domains = Some(vec![

“http://127.0.0.1:3500”.to_string(),

]);

let module = “tests/dapr/build/optimized.wasm”;

create_instance(module.to_string(), allowed_domains.clone()).unwrap();

}

最后更多分享:前端字节跳动真题解析

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

s_]( )

fn main() {

let allowed_domains = Some(vec![

“http://127.0.0.1:3500”.to_string(),

]);

let module = “tests/dapr/build/optimized.wasm”;

create_instance(module.to_string(), allowed_domains.clone()).unwrap();

}

最后更多分享:前端字节跳动真题解析

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • [外链图片转存中…(img-cQdAazXB-1714388867252)]
  • 30
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值