当前位置: 首页 > article >正文

wasm在云原生领域的运用

Wasm 最初是以浏览器安全沙盒为目的开发的,发展到目前为止,WebAssembly 已经成为一个用于云原生软件组件的高性能、跨平台和多语言软件沙箱环境,Wasm 轻量级容器也非常适合作为下一代无服务器平台运行时

Envoy 社区在 Envoy 中嵌入了 WASM 虚拟机以获得一个安全的沙箱环境,用于动态加载和运行可拔插的扩展代码(被编译为 WASM 字节码),简化 Envoy 二次开发和功能增强的复杂度

prxoy_wasm 由一个关键的外部依赖提供,由 Envoy 社区和 Istio 社区等共同维护。它包含了对 WASM 虚拟机的封装。

并推出 针对代理的 WebAssembly (Wasm) (Proxy-Wasm):包括一个会标准化的ABI,SDK,

https://github.com/proxy-wasm/spec/pull/42/files?short_path=39c0fcb#diff-39c0fcbaec7f6ffb311e442b6f0774bf3c050cd9b3318f51f55c2d6c38d4976d

比如这样一个接口规范

#### `proxy_on_request_body`


- params:- `i32 (uint32_t) stream_context_id`
  - `i32 (size_t) body_size`
  - `i32 (bool) end_of_stream`
- returns:- `i32 (`[`proxy_action_t`](https://github.com/proxy-wasm/spec/diffs/0?base_sha=86719f51b29cc1fcdf2d07ae80a6cc7bae0bc99d&head_user=PiotrSikora&name=v0.2.1&pull_number=42&sha1=86719f51b29cc1fcdf2d07ae80a6cc7bae0bc99d&sha2=3bf9d055ecab9ac2e25883c5f4f5082c1bda7a2b&short_path=39c0fcb&unchanged=expanded&w=false#proxy_action_t)`) action`


Called for each chunk of HTTP request body received from downstream, even when the processing is paused.
Request body chunk (of `body_size`) can be retrieved and/or modified using [`proxy_get_buffer_bytes`](https://github.com/proxy-wasm/spec/diffs/0?base_sha=86719f51b29cc1fcdf2d07ae80a6cc7bae0bc99d&head_user=PiotrSikora&name=v0.2.1&pull_number=42&sha1=86719f51b29cc1fcdf2d07ae80a6cc7bae0bc99d&sha2=3bf9d055ecab9ac2e25883c5f4f5082c1bda7a2b&short_path=39c0fcb&unchanged=expanded&w=false#proxy_get_buffer_bytes) and/or [`proxy_set_buffer_bytes`](https://github.com/proxy-wasm/spec/diffs/0?base_sha=86719f51b29cc1fcdf2d07ae80a6cc7bae0bc99d&head_user=PiotrSikora&name=v0.2.1&pull_number=42&sha1=86719f51b29cc1fcdf2d07ae80a6cc7bae0bc99d&sha2=3bf9d055ecab9ac2e25883c5f4f5082c1bda7a2b&short_path=39c0fcb&unchanged=expanded&w=false#proxy_set_buffer_bytes) with `buffer_id` set to `HTTP_REQUEST_BODY`.
`body_size` represents total available size of the body that can be retrieved, and its value will increment if the processing is paused and the body is buffered by the host and not forwarded upstream.
Paused HTTP request can be resumed using [`proxy_continue_stream`](https://github.com/proxy-wasm/spec/diffs/0?base_sha=86719f51b29cc1fcdf2d07ae80a6cc7bae0bc99d&head_user=PiotrSikora&name=v0.2.1&pull_number=42&sha1=86719f51b29cc1fcdf2d07ae80a6cc7bae0bc99d&sha2=3bf9d055ecab9ac2e25883c5f4f5082c1bda7a2b&short_path=39c0fcb&unchanged=expanded&w=false#proxy_continue_stream) or closed using [`proxy_close_stream`](https://github.com/proxy-wasm/spec/diffs/0?base_sha=86719f51b29cc1fcdf2d07ae80a6cc7bae0bc99d&head_user=PiotrSikora&name=v0.2.1&pull_number=42&sha1=86719f51b29cc1fcdf2d07ae80a6cc7bae0bc99d&sha2=3bf9d055ecab9ac2e25883c5f4f5082c1bda7a2b&short_path=39c0fcb&unchanged=expanded&w=false#proxy_close_stream) with `stream_type` set to `HTTP_REQUEST`.
Additionally, as long as HTTP response headers were not send downstream, a HTTP response can be sent using [`proxy_send_local_response`](https://github.com/proxy-wasm/spec/diffs/0?base_sha=86719f51b29cc1fcdf2d07ae80a6cc7bae0bc99d&head_user=PiotrSikora&name=v0.2.1&pull_number=42&sha1=86719f51b29cc1fcdf2d07ae80a6cc7bae0bc99d&sha2=3bf9d055ecab9ac2e25883c5f4f5082c1bda7a2b&short_path=39c0fcb&unchanged=expanded&w=false#proxy_send_local_response).
Plugin must return one of the following values:
- `CONTINUE` to forward `HTTP_REQUEST_BODY` buffer upstream.
- `PAUSE` to pause processing.

下面我们来看下go-sdk里面的实现:
https://github.com/tetratelabs/proxy-wasm-go-sdk

//export proxy_on_request_body
func proxyOnRequestBody(contextID uint32, bodySize int, endOfStream bool) types.Action {
   if recordTiming {
      defer logTiming("proxyOnRequestBody", time.Now())
   }
   ctx, ok := currentState.httpContexts[contextID]
   if !ok {
      panic("invalid context on proxy_on_request_body")
   }
   currentState.setActiveContextID(contextID)
   return ctx.OnHttpRequestBody(bodySize, endOfStream)
}

可以看到每个实现的接口都有一个export标签,所以说proxy-wasm本质上还是遵循wasi规范,这样可以在编译为wasm文件的时候,能够被wasm任意虚拟机解析并调用。

Envoy使用WASM虚拟机(如WAVM或Wasmtime)加载和执行WASM模块。以下是Envoy解析WASM文件的过程:

  1. 配置WASM插件

在Envoy配置文件中,你需要配置WASM插件。配置文件中的wasm字段指定了WASM模块的路径、虚拟机类型、配置数据等信息。例如:

wasm:
  config:
    name: "my_plugin"
    root_id: "my_root_id"
    vm_config:
      runtime: "envoy.wasm.runtime.wavm"
      configuration:
        "@type": "type.googleapis.com/google.protobuf.StringValue"
        value: "my_plugin_config"
    vm_id: "my_vm_id"
    vm_type: "plugin"
    vm_environment:
      runtime_supports_wasi: true
  1. 加载WASM模块

Envoy使用配置文件中指定的虚拟机类型(如WAVM或Wasmtime)加载WASM模块。加载过程包括以下步骤:

  • 读取WASM文件。

  • 验证WASM文件的格式和结构。

  • 将WASM文件编译为宿主机器代码。

  • 初始化WASM虚拟机。

  1. 实例化WASM模块

Envoy使用配置文件中指定的根ID(root_id)实例化WASM模块。实例化过程包括以下步骤:

  • 分配内存。

  • 初始化全局变量。

  • 调用WASM模块的_start函数。

  1. 调用WASM模块的导出函数

Envoy通过ABI(应用程序二进制接口)与WASM模块进行交互。ABI定义了WASM模块中导出的函数和数据结构,这些函数和数据结构允许Envoy访问WASM模块的功能。Envoy在特定的事件(如HTTP请求、TCP连接等)上调用WASM模块的导出函数,并传递相关的数据。

  1. 销毁WASM模块

当WASM模块不再需要时,Envoy会销毁WASM模块,释放资源。
总之,Envoy通过配置文件中指定的虚拟机类型加载和执行WASM模块,并通过ABI与WASM模块进行交互。在开发基于Envoy的WASM插件时,你需要实现ABI中定义的导出函数,并根据需要调用Envoy的API。

在Istio中,你需要使用EnvoyFilter资源来配置WASM插件。EnvoyFilter资源允许你在Envoy代理中添加、修改或删除配置。你需要在EnvoyFilter资源中指定WASM模块的路径、虚拟机类型、配置数据等信息。例如:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: my-wasm-plugin
spec:
  workloadSelector:
    labels:
      app: my-app
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INBOUND
      listener:
        filterChain:
          filter:
            name: "envoy.filters.network.http_connection_manager"
            subFilter:
              name: "envoy.filters.http.router"
    patch:
      operation: INSERT_BEFORE
      value:
        name: "envoy.filters.http.wasm"
        typed_config:
          "@type": "type.googleapis.com/udpa.type.v1.TypedStruct"
          type_url: "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm"
          value:
            config:
              name: "my_plugin"
              root_id: "my_root_id"
              vm_config:
                runtime: "envoy.wasm.runtime.wavm"
                configuration:
                  "@type": "type.googleapis.com/google.protobuf.StringValue"
                  value: "my_plugin_config"
                vm_id: "my_vm_id"
                vm_type: "plugin"
                vm_environment:
                  runtime_supports_wasi: true

https://cloudnative.to/blog/envoy-wasm-source-deep-dive/


http://www.kler.cn/news/342235.html

相关文章:

  • 【进阶OpenCV】 (6)--指纹识别
  • 每天一个数据分析题(四百九十九)- 数据集
  • 跨界的胜利:机器学习与神经网络的物理之光
  • Spring Boot中使用RabbitMQ 生产消息和消费消息
  • linux线程 | 线程的概念
  • npm依赖版本锁定详解
  • python 实现寻找无向图的关节点Articulation Points算法
  • 开源全文搜索(搜索引擎)
  • 【项目配置文件】TypeScript 编译器的配置文件
  • Spring Boot大学生就业招聘系统的开发与部署
  • 如何确保微服务架构的高并发
  • 使用Go语言的gorm框架查询数据库并分页导出到Excel实例(包含源代码,可以直接运行)
  • C++ 观察者模式
  • 架构与思维:漫谈高并发业务的CAS及ABA
  • 第十届MathorCup高校数学建模挑战赛-A题:基于 logistic 回归和 DEA 模型对无车承运平台线路定价问题的优化和评价
  • 需求10——通过改一个小bug来学习如何定位问题
  • 系统移植二和网卡移植实验和私有驱动LED的移植
  • Codeforces Round 977 (Div. 2)E1 Digital Village (Easy Version)(Floyd,贪心)
  • 力扣 前缀和
  • Nginx 和 Lua 设计黑白名单