强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

11 - 边缘计算

11 - 边缘计算

边缘计算是 WebAssembly 增长最快的非浏览器应用场景——快速启动、沙箱安全、跨平台。


11.1 为什么 Wasm 适合边缘计算?

特性WasmDocker 容器原生函数
冷启动时间< 1ms100ms - 数秒< 1ms
内存占用KB 级MB 级KB 级
安全沙箱✅ 内建⚠️ 需配置❌ 无
跨平台⚠️ 依赖架构
语言无关
二进制大小KB - MB数十 MBKB - MB

边缘计算的优势

用户 ──────► 边缘节点 ──────► 源站
  │              │
  │ <10ms延迟    │ 100-500ms 延迟
  │              │
  └──────────────┘
  边缘节点部署在离用户最近的网络节点

11.2 Cloudflare Workers

Cloudflare Workers 是最早大规模支持 Wasm 的边缘计算平台,全球有 300+ 节点。

快速开始

# 使用 Wrangler CLI
npm create cloudflare@latest my-worker
cd my-worker

# 选择 "Hello World" 模板
# wrangler.toml 中配置 Wasm

项目配置

# wrangler.toml
name = "my-wasm-worker"
main = "src/index.js"
compatibility_date = "2024-01-01"

# 方式 1:直接引用 Wasm 文件
[[wasm_modules]]
MODULE_WASM = "wasm/module.wasm"

# 方式 2:通过构建脚本
[build]
command = "cargo install wasm-pack && wasm-pack build --target web"

Rust + wasm-bindgen 示例

// src/lib.rs
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn process_request(url: &str, body: &str) -> String {
    // 在边缘节点执行的逻辑
    let hash = compute_hash(body);
    let timestamp = js_sys::Date::now();
    
    format!(
        r#"{{"url":"{}","hash":"{}","timestamp":{},"processed_at":"edge"}}"#,
        url, hash, timestamp
    )
}

fn compute_hash(data: &str) -> String {
    // 使用 blake3 等轻量哈希
    use std::collections::hash_map::DefaultHasher;
    use std::hash::{Hash, Hasher};
    
    let mut hasher = DefaultHasher::new();
    data.hash(&mut hasher);
    format!("{:x}", hasher.finish())
}
// src/index.js — Worker 入口
import { process_request } from '../pkg/my_wasm.js';

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    const body = await request.text();
    
    const result = process_request(url.pathname, body);
    
    return new Response(result, {
      headers: { 'Content-Type': 'application/json' }
    });
  }
};

纯 Rust Worker

// 使用 worker-rs crate
use worker::*;

#[event(fetch)]
async fn main(req: Request, env: Env, _ctx: Context) -> Result<Response> {
    let router = Router::new();
    
    router
        .get_async("/api/:name", |_req, ctx| async move {
            let name = ctx.param("name").unwrap();
            Response::ok(format!("Hello, {}!", name))
        })
        .post_async("/api/process", |mut req, _ctx| async move {
            let body = req.text().await?;
            let result = process_data(&body);
            Response::ok(result)
        })
        .run(req, env)
        .await
}

KV 存储与 D1 数据库

use worker::*;

#[event(fetch)]
async fn main(req: Request, env: Env, _ctx: Context) -> Result<Response> {
    // KV 存储
    let kv = env.kv("MY_KV")?;
    kv.put("key", "value")?.execute().await?;
    let value = kv.get("key").text().await?;
    
    // D1 数据库
    let db = env.d1("MY_DB")?;
    let stmt = db.prepare("SELECT * FROM users WHERE id = ?");
    let row = stmt.bind(&[1.into()])?.first(None).await?;
    
    Response::ok(format!("KV: {}, DB: {:?}", value, row))
}

11.3 Fastly Compute

Fastly Compute 是另一个成熟的 Wasm 边缘计算平台,使用 Wasmtime 运行时。

快速开始

# 安装 Fastly CLI
brew install fastly/tap/fastly

# 创建项目
fastly compute init --language=rust

# 构建
fastly compute build

# 本地测试
fastly compute serve

# 部署
fastly compute deploy

Rust 示例

use fastly::http::{Method, StatusCode};
use fastly::{Error, Request, Response};

#[fastly::main]
fn main(req: Request) -> Result<Response, Error> {
    match (req.get_method(), req.get_path()) {
        (&Method::GET, "/") => {
            Ok(Response::from_status(StatusCode::OK)
                .with_body_text_plain("Hello from Fastly Compute!"))
        }
        
        (&Method::POST, "/api/transform") => {
            let body = req.into_body_str();
            let transformed = transform_data(&body);
            Ok(Response::from_status(StatusCode::OK)
                .with_body_text_html(&transformed)
                .with_header("Content-Type", "application/json"))
        }
        
        _ => Ok(Response::from_status(StatusCode::NOT_FOUND))
    }
}

fn transform_data(input: &str) -> String {
    // 边缘数据转换逻辑
    format!(r#"{{"input_length":{},"transformed_at":"edge"}}"#, input.len())
}

Fastly 特性

特性说明
Geolocation根据 IP 获取地理位置
KV Store全球分布式键值存储
Config Store配置管理
Secret Store敏感信息管理
Backend API代理到后端服务
Edge Dictionary低延迟字典

11.4 WasmEdge

WasmEdge 是一个高性能的 Wasm 运行时,特别适合边缘设备和 AI 推理场景。

安装

# 一键安装
curl -sSf https://raw.githubusercontent.com/nicedoc/nicedoc.io/master/install.sh | bash

# 或使用包管理器
brew install wasmedge

AI 推理集成

// 使用 WasmEdge 的 TensorFlow Lite 扩展
use wasmedge_tensorflow_interface::*;

fn classify_image(image_data: &[u8]) -> Vec<(String, f32)> {
    let model_data = include_bytes!("model.tflite");
    let labels = include_str!("labels.txt");
    
    let mut session = TensorflowSession::new(
        model_data,
        TensorflowModelType::TensorflowLite,
        TensorflowTarget::CPU,
    );
    
    session.add_input("input", image_data)
        .run()
        .expect("Inference failed");
    
    let output = session.get_output("output");
    // 解析输出...
    
    vec![]
}

命令行运行

# 运行 WASI 应用
wasmedge --dir .:. app.wasm

# 启用 TensorFlow 支持
wasmedge-tensorflow-lite app.wasm

# 启用网络支持
wasmedge --dir .:. --nn-preload default:tensorflowlite:model.tflite app.wasm

11.5 Deno Deploy

// Deno Deploy 原生支持 Wasm
const wasmModule = await WebAssembly.compile(
  await Deno.readFile("./module.wasm")
);

Deno.serve(async (req) => {
  const instance = await WebAssembly.instantiate(wasmModule);
  const result = instance.exports.process(await req.text());
  return new Response(String(result));
});

11.6 IoT 应用

Wasm 在 IoT 中的优势

传统 IoT 开发:
  每种硬件 → 交叉编译 → 不同固件
  维护 N 个版本 × M 种设备

Wasm + IoT:
  源代码 → 编译为 Wasm → 任何设备
  维护 1 个版本
  + 安全沙箱(防止恶意代码访问硬件)
  + OTA 更新(只需传输 .wasm 文件)

TinyGo + Wasm

// 使用 TinyGo 编译为 WASI
package main

import (
    "fmt"
    "math"
)

// 传感器数据处理
type SensorData struct {
    Temperature float64
    Humidity    float64
    Pressure    float64
}

func (s SensorData) HeatIndex() float64 {
    // 计算体感温度
    t := s.Temperature
    h := s.Humidity
    return -8.7847 + 1.6114*t + 2.3385*h - 0.1461*t*h +
        -0.0123*t*t - 0.0164*h*h + 0.0022*t*t*h +
        0.0007*t*h*h - 0.0000036*t*t*h*h
}

func main() {
    data := SensorData{Temperature: 25.0, Humidity: 60.0, Pressure: 1013.25}
    fmt.Printf("Heat Index: %.2f\n", data.HeatIndex())
}
# 使用 TinyGo 编译
tinygo build -target wasi -o sensor.wasm main.go

# 在 IoT 设备上运行
wasm3 sensor.wasm

11.7 边缘函数实战:A/B 测试

use fastly::http::{Method, StatusCode};
use fastly::{Error, Request, Response};

static VARIANT_A: &str = r#"<h1>Welcome to Variant A</h1>"#;
static VARIANT_B: &str = r#"<h1>Welcome to Variant B</h1>"#;

#[fastly::main]
fn main(req: Request) -> Result<Response, Error> {
    let cookie = req.get_header("Cookie").map(|v| v.to_str().unwrap_or(""));
    
    let variant = match cookie {
        Some(c) if c.contains("variant=a") => "A",
        Some(c) if c.contains("variant=b") => "B",
        _ => {
            // 随机分配(使用简单的确定性哈希)
            let ip = req.get_client_ip_addr().map(|ip| ip.to_string()).unwrap_or_default();
            if ip.as_bytes().last().unwrap_or(&0) % 2 == 0 { "A" } else { "B" }
        }
    };
    
    let body = if variant == "A" { VARIANT_A } else { VARIANT_B };
    
    Ok(Response::from_status(StatusCode::OK)
        .with_body_text_html(body)
        .with_header("Set-Cookie", format!("variant={}; Path=/; Max-Age=86400", variant))
        .with_header("X-Variant", variant))
}

11.8 边缘计算 vs 云函数

维度边缘计算 (Wasm)云函数 (Lambda)
冷启动< 1ms50ms - 数秒
延迟10-50ms(取决于位置)50-500ms
定价按请求计费按请求+时长计费
全球分布300+ 节点需要配置多区域
运行时限制CPU 时间限制CPU+内存+时间限制
文件系统有限/无临时存储 /tmp
最大执行时间通常 30s15 分钟
适用场景API 网关、路由、边缘逻辑复杂计算、批处理

11.9 注意事项

⚠️ CPU 时间限制:边缘计算平台通常限制单次请求的 CPU 时间(如 Cloudflare Workers 免费版限制 10ms CPU 时间)。

⚠️ 内存限制:边缘节点内存有限(通常 128MB),大型 Wasm 模块可能无法加载。

⚠️ 无持久化文件系统:大多数边缘平台不提供持久化文件系统,需要使用 KV 存储或外部数据库。

⚠️ 冷启动优化:虽然 Wasm 冷启动快,但模块越大,编译时间越长。保持模块精简是关键。


11.10 扩展阅读


下一章12 - 插件系统 — 使用 Wasm 构建安全的插件和扩展机制。