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

  • 模块化越来越高- 更加细粒度的计算单元,如容器和 Serverless 函数,更加适于微服务架构的应用交付,可以更加充分利用云的能力,提升架构敏捷性。

  • 可编程性越来越高- 可以通过声明式 API 和策略进行实现自动化管理与运维,可以通过 Immutable Infrastructure (不可变基础设施)进一步提升分布式应用运维的确定性。

  • 弹性效率越来越高- VM 可以实现分钟级扩容;容器与 Serverless 容器可以实现秒级扩容;借助调度优化,函数可以做到毫秒级扩容。

  • 韧性越来越高- Kubernetes 提供了强大自动化编排能力,提升应用系统自愈性。而 Serverless 进一步将稳定性、可伸缩性和安全等系统级别复杂性下沉到基础设施,开发者只需关注自身业务应用逻辑,进一步释放了生产力,提升系统的可恢复能力。

分布式云则是云计算发展的另外一个重要趋势,公有云的服务可以拓展到不同的物理位置,让计算进一步贴近客户。分布式云让客户享受云计算的便利的同时,也可以满足对计算实时性和安全合规的诉求。这也推动了企业应用架构的变化 - 应用要能够在不同的环境进行部署、迁移,以最优化的方式提供服务。

进一步随着移动互联网,AI 与 IoT 等新技术的涌现,无处不在的计算已经成为现实。与此同时,这也在催生算力的多样性,X86 架构一统天下的时代已经过去,ARM/RISC-V 等芯片新势力不但称雄移动通信和嵌入式设备领域,也在向边缘计算和数据中心市场发起进攻。开发者甚至需要让应用支持不同的 CPU 体系架构,比如我们可以将一个图像识别应用部署在边缘或者 IoT 等不同环境、不同体系架构的设备之上运行。

在分布式云、边缘计算、云端一体等新的云计算场景下,下一代云原生应用运行时将具备什么样的特点?

下一代云原生应用运行时

================================================================================

1. 无处不在的计算催生下一代可移植、高性能、轻量化的安全沙箱


容器应用采用自包含的打包方式 – 容器镜像,它包含了应用代码和依赖的系统组件,可以实现应用与基础设施解耦,让应用可以在公共云、专有云等不同的运行环境以一致的方式进行部署、运维,简化了弹性和迁移。此外 Docker 镜像规范支持多架构(Multi-Arch)镜像,可以简化不同 CPU 体系架构(如 x86, ARM 等)的应用镜像的构建与分发。

函数应用只包含用于事件响应的代码包,这将应用交付格式从原生二进制文件提升到了高级语言层面。这也给应用的可移植性带来了更大的想象空间,理论上甚至可以屏蔽执行环境 CPU 体系架构的差异。比如对于不依赖本地代码的 Python/NodeJS 等脚本或者 Java 应用,无需修改就可以在 x86 或者 ARM 等不同 CPU 架构上运行。

然而理想很丰满,现实很骨感,可移植性和厂商锁定是函数 PaaS 发展的拦路虎。

  • 很多脚本代码依然需要通过调用原生代码来实现数据处理和调用中间件(如数据库驱动),但是编译原生代码需要构建环境与目标执行环境一致才能保障兼容性。比如 AWS Lambda / 阿里云函数计算都要求二进制原生代码依赖指定的内核和 libc 版本。因此,越来越多的函数 PaaS 服务支持容器镜像作为载体,来简化函数应用打包和依赖管理。

  • 函数应用通常依赖后端服务(BaaS, Backend as a Service)实现数据访问与计算处理等能力,由于 BaaS 不存在任何标准,这样很难将在 AWS Lambda 上开发的函数应用移植到阿里云的函数计算服务。

在 Serverless 计算中,现有的主流技术是利用沙箱容器技术,如 AWS Firecraker 或者阿里云沙箱容器,来实现强隔离的安全执行环境,但是也带来更大的资源消耗。虽然现在阿里云沙箱容器经过优化可以实现 300ms 的冷启动速度,接近 Docker 这样的 OS 容器启动速度,但是还无法满足函数 PaaS 毫秒级的启动要求,目前需要通过的调度策略,预留一定的 standby 实例才可以满足,但是这样也引入了更多的资源消耗。

WebAssembly(WASM) 是一个新的 W3C 规范,是一个通用、开放、高效、安全的底层虚拟机抽象。它的设计初衷是为了解决JavaScript的性能问题,使得 Web 应用有接近本机原生应用的性能。可以将现有编程语言应用,如 C/C++, Rust 等,编译成为 WASM 的字节码,运行在浏览器中的一个沙箱环境中。

WASM 让应用开发技术与运行时环境解耦,极大促进了代码复用。Mozilla 更在 2019 年推出了 WebAssembly System Interface(WASI),它提供类似 POSIX 这样的标准 API 来标准化 WebAssembly 与系统资源的交互抽象,比如文件系统访问,内存管理等。WASI 的出现拓展了 WASM 的应用场景,可以让其作为一个虚拟机运行各种类型的服务端应用。WASM/WASI 为应用的可移植性带来全新的希望,为了进一步推动 WebAssembly 生态发展,Mozilla、Fastly、英特尔和红帽公司携手成立了字节码联盟(Bytecode Alliance),共同领导 WASI 标准、 WebAssembly 运行时、工具等工作。

WebAssembly 所具备的的安全、可移植、高效率,轻量化的特点,为应用沙箱的发展带来了全新的思路。WASM 可以轻松实现毫秒级冷启动时间和极低的资源消耗。同时 WASM 字节码比原生机器码有更高的安全级别。此外,WASI 实现了细粒度基于能力的安全模型,遵循最小权限原则。在执行过程中,WASI 应用只能访问由依赖注入指明的确切资源集,这种方式与传统粗粒度的操作系统级隔离相比,进一步收敛了安全攻击面。

正因如此,WASM/WASI 得到了 Serverless、IoT/边缘计算等社区的广泛关注。Fastly、Cloudflare 等厂商相继发布了基于 WebAssembly 技术实现了更加轻量化的 Serverless 服务。

然而 WebAssembly 在服务器端的应用之路依然布满荆棘。首先 WASI 的能力还在非常早期的状态,一些关键能力依然缺失,首当其冲的就是缺乏标准化的网络访问能力:https://github.com/WebAssembly/WASI/issues/315

目前 WASI 应用仅能做一些计算类任务,基本无法实现分布式应用,也无法调用多样性的后端服务和 Redis、MySQL、Kafka 等应用中间件。这大大限制了 WASI 的应用场景。

当理想撞上现实,头破血流还是绝处逢生?

2. 下一代可移植应用运行时加速编程界面上移,应用基础设施能力下沉


Dapr 是微软开源的面向云原生应用的分布式应用运行时,目标使所有开发人员能够使用任何语言和任何框架轻松地构建弹性的、事件驱动的、可移植的微服务应用。

3.jpg

Dapr 实现了一系列构建高性能、可伸缩、高可用的分布式应用的设计模式,比如提供了服务发现和服务调用能力,也实现了一个简单、一致的编程模型来支持事件驱动应用架构。

此外 Dapr 通过基础设施屏蔽了应用访问后端服务的技术细节,如资源绑定、安全管理,可观测性等等。这个对 Serverless 应用非常重要,一方面将开发和部署进行了解耦,让开发者和运维团队可以通过关注点分离简化系统复杂性;一方面,可以将短生命周期、无状态的 Serverless 应用逻辑,与数据库连接池管理这样的长期运行,有状态的中间件访问能力进行解耦,提升了 Serverless 应用的可伸缩性和运行效率。

“Any language, any framework, anywhere” 是 Dapr 的重要设计目标。Dapr 通过在应用和后端服务之间,通过 Sidecar 方式提供一个抽象层,并通过标准化的 HTTP/gRPC API 实现了应用的可移植性,和后端服务的可替换性。

走向诗和远方

===========================================================================

4.jpg

我们可以将 WebAssembly 和 Dapr 相结合,来实现可移植、强隔离、轻量化的微服务应用架构。Dapr sidecar 与 WASM 虚拟机部署在一起。WASI 应用通过 HTTP/gRPC 访问本地的 Dapr 服务端点,由 Dapr 代理连接各种后端服务或者实现服务间通信。

这样的架构设计让 WASI 应用的安全边界非常清晰,符合 WASI 安全模型,WASI 应用只能通过 Dapr sidecar 实现外部服务访问。同时在这个架构中,只有 WASM 虚拟机和 Dapr 作为可信的环境依赖以原生机器码运行。而应用是可移植的 WASM 字节码,大大提升了架构的可移植性和安全性。

来自微软 Deis Labs 的 Radu Matei,最近提供了一个实验性项目可以为 WASI 添加 HTTP 支持。详见:_https://deislabs.io/posts/wasi-experimental-http/ _

在此基础上,我们来构建一个最小原型,验证 WebAssembly 与 Dapr 相结合的技术可行性。

1. Dapr 环境准备


我们首先按照 https://docs.dapr.io/getting-started/ 的流程:

$ 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)

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-XtRIKkr9-1715707374001)]

[外链图片转存中…(img-0FKkmttc-1715707374001)]

[外链图片转存中…(img-pVrKQikZ-1715707374002)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值