构建api gateway之 openresty 中如何使用 wasm
openresty 中如何使用 wasm
WASM 是什么?
WebAssembly是一种运行在现代网络浏览器中的新型代码,并且提供新的性能特性和效果。它设计的目的不是为了手写代码而是为诸如C、C++和Rust等低级源语言提供一个高效的编译目标。
对于网络平台而言,这具有巨大的意义——这为客户端app提供了一种在网络平台以接近本地速度的方式运行多种语言编写的代码的方式;在这之前,客户端app是不可能做到的。
而且,你在不知道如何编写WebAssembly代码的情况下就可以使用它。WebAssembly的模块可以被导入的到一个网络app(或Node.js)中,并且暴露出供JavaScript使用的WebAssembly函数。JavaScript框架不但可以使用WebAssembly获得巨大性能优势和新特性,而且还能使得各种功能保持对网络开发者的易用性。
比如在envoy 中,主要是通过wasm 提供多语言开发扩展envoy功能的目的
openresty如何玩?
那么在openresty 中是否也可以这么集成wasm呢?
当然是可以的,毕竟openresty 本身就是 nginx + lua , 再加一个 wasm vm 进去也是一样可以做到的。
利用nginx模块化系统就可以做到这个事情了
由于模块的代码都是 c, 大家都不太有兴趣,
这里就不细说了, 有兴趣的小伙伴 可以在 api7/wasm-nginx-module 这里了解细节
nginx 模块怎么开发可以看 nginx 模块开发 - Google 搜索
proxy-wasm是什么?
这里重点提 proxy-wasm 这个东西, 它是上述加在nginx 中的wasm 模块中的 api 标准集合
最初出现与 envoy, 现在也是 Istio 1.6 之后扩展选项, 如下图
目前支持如下
SDKs
- AssemblyScript SDK
- C++ SDK
- Go (TinyGo) SDK
- Rust SDK
- Zig SDK
Servers
- Envoy
- Istio Proxy (Envoy-based)
- MOSN
- OpenResty (work-in-progress)
- ATS (proof-of-concept)
Libraries
openresty 中使用wasm 的例子
1. 基于 assemblyscript 的示例代码
内容主要为添加 response header
export * from "@solo-io/proxy-runtime/assembly/proxy"; // this exports the required functions for the proxy to interact with us.
import { RootContext, Context, registerRootContext, FilterHeadersStatusValues, stream_context } from "@solo-io/proxy-runtime/assembly";
class AddHeaderRoot extends RootContext {
createContext(context_id: u32): Context {
return new AddHeader(context_id, this);
}
}
class AddHeader extends Context {
constructor(context_id: u32, root_context: AddHeaderRoot) {
super(context_id, root_context);
}
onResponseHeaders(a: u32, end_of_stream: bool): FilterHeadersStatusValues {
const root_context = this.root_context;
if (root_context.getConfiguration() == "") {
stream_context.headers.response.add("hello", "world!");
} else {
stream_context.headers.response.add("hello", root_context.getConfiguration()); // 添加 response header
}
return FilterHeadersStatusValues.Continue;
}
}
registerRootContext((context_id: u32) => { return new AddHeaderRoot(context_id); }, "add_header");
编译可以得到,我们只需要 release.wasm 文件其实

2. 为 openresty 按照 wasm
重新构建 openresty 并安装 wasm 模块, 如下为对应脚本 build.sh
#!/usr/bin/env bash
# prev_workdir="$PWD"
# repo=$(basename "$prev_workdir")
# workdir=$(mktemp -d)
# cd "$workdir" || exit 1
# echo $workdir
or_ver="$1"
cc_opt=${cc_opt:-}
ld_opt=${ld_opt:-}
luajit_xcflags=${luajit_xcflags:="-DLUAJIT_NUMMODE=2 -DLUAJIT_ENABLE_LUA52COMPAT"}
OR_PREFIX=${OR_PREFIX:="/usr/local/openresty"}
debug_args=${debug_args:-}
wasm_nginx_module_ver="0.6.2"
git clone --depth=1 -b $wasm_nginx_module_ver \
https://github.com/api7/wasm-nginx-module.git \
wasm-nginx-module-${wasm_nginx_module_ver}
cd wasm-nginx-module-${wasm_nginx_module_ver} || exit 1
./install-wasmtime.sh
cd ..
cd openresty-${or_ver} || exit 1
./configure --prefix="$OR_PREFIX" \
--with-cc-opt="$cc_opt" \
--with-ld-opt="-Wl,-rpath,$OR_PREFIX/wasmtime-c-api/lib $ld_opt" \
$debug_args \
--add-module=../wasm-nginx-module-${wasm_nginx_module_ver} \
--with-poll_module \
--with-pcre-jit \
--without-http_rds_json_module \
--without-http_rds_csv_module \
--without-lua_rds_parser \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-http_v2_module \
--without-mail_pop3_module \
--without-mail_imap_module \
--without-mail_smtp_module \
--with-http_stub_status_module \
--with-http_addition_module \
--with-http_auth_request_module \
--with-http_secure_link_module \
--with-http_random_index_module \
--with-http_gzip_static_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-threads \
--with-compat \
--with-luajit-xcflags="$luajit_xcflags" \
-j`nproc`
make -j`nproc`
make install DESTDIR="$PWD"
OPENRESTY_PREFIX="$PWD$OR_PREFIX"
cd ..
cd wasm-nginx-module-${wasm_nginx_module_ver} || exit 1
OPENRESTY_PREFIX="$OPENRESTY_PREFIX" make install
cd ..
运行
#!/usr/bin/env bash
or_ver="1.21.4.1"
tempdir=$(mktemp -d)
echo "do at ${tempdir}"
cp -R ./ ${tempdir}
cd ${tempdir}
wget --no-check-certificate https://openresty.org/download/openresty-${or_ver}.tar.gz
tar -zxvpf openresty-${or_ver}.tar.gz > /dev/null
sh build.sh $or_ver
3. 测试
这里就只列举 demo 文件,感兴趣的自己测试
worker_processes 1;
worker_cpu_affinity auto;
worker_rlimit_nofile 65535;
events {
use epoll;
worker_connections 65535;
accept_mutex off;
multi_accept on;
}
http {
lua_package_path "${prefix}deps/share/lua/5.1/?.lua;${prefix}deps/share/lua/5.1/?/init.lua;${prefix}?.lua;${prefix}?/init.lua;;./?.lua;/usr/local/openresty/luajit/share/luajit-2.1.0-beta3/?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/openresty/luajit/share/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/?/init.lua;";
lua_package_cpath "${prefix}deps/lib64/lua/5.1/?.so;${prefix}deps/lib/lua/5.1/?.so;;./?.so;/usr/local/lib/lua/5.1/?.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall.so;";
lua_socket_log_errors off;
wasm_vm wasmtime; # wasm 运行时设置
init_by_lua_block { # 初始化加载可以复用wasm。避免运行时加载的损耗
wasm = require("resty.proxy-wasm")
plugin = wasm.load("add_header", "/app/wasm/assemblyscript/build/release.wasm")
}
server {
listen 80;
server_tokens off;
location /t {
return 200;
header_filter_by_lua_block { # 这里设置调用 wasm
local ctx = wasm.on_configure(plugin, 'add_header')
wasm.on_http_response_headers(ctx)
}
}
location /d {
return 200;
header_filter_by_lua_block {
ngx.header['test'] = 'add_header'
}
}
}
}
构建api gateway之 openresty 中如何使用 wasm的更多相关文章
- 构建api gateway之 动态插件
动态插件 之前已经拆解细点逐个介绍了 tcp .http 代理相关核心点,现在介绍一个让 api gateway 变得很灵活的功能实现: 动态插件. 由于 lua 的动态语言特点,我们可以比较方便做到 ...
- 构建api gateway之 健康检查
Healthcheck 由于服务无法保证永远不会下线,而且下线时不一定能有人员能及时发现, 所以api gateway 一般会引入一个监工 Healthcheck, 像大家每年体检一样定时确认服务是否 ...
- 构建api gateway之 http路由实现
http路由 路由是指路由器从一个接口上收到数据包,根据数据包的目的地址进行定向并转发到另一个接口的过程. 而这里的http路由其实等同于web开发中,根据http相关参数(比如url.http me ...
- 构建api gateway之 负载均衡
什么是负载均衡 负载均衡,英文名称为Load Balance,其含义就是指将负载(工作任务)进行平衡.分摊到多个操作单元上进行运行 以下为几种负载均衡策略介绍 1.随机(Random) 大家很多时候说 ...
- 构建api gateway之 基于etcd实现动态配置同步
配置中心 在之前 tcp的yaml配置 介绍了如何监听yaml文件变化然后更新配置. 当然假如我们有很多实例,那么yaml改动将是非常痛苦的事情,那么如何做到配置文件统一管理,实时更新呢? 我们可以引 ...
- 谈谈微服务中的 API 网关(API Gateway)
前言 又是很久没写博客了,最近一段时间换了新工作,比较忙,所以没有抽出来太多的时间写给关注我的粉丝写一些干货了,就有人问我怎么最近没有更新博客了,在这里给大家抱歉. 那么,在本篇文章中,我们就一起来探 ...
- 微服务中的 API 网关(API Gateway)
API 网关(API Gateway)提供高性能.高可用的 API 托管服务,帮助用户对外开放其部署在 ECS.容器服务等云产品上的应用,提供完整的 API 发布.管理.维护生命周期管理.用户只需进行 ...
- 服务中的 API 网关(API Gateway)
我们知道在微服务架构风格中,一个大应用被拆分成为了多个小的服务系统提供出来,这些小的系统他们可以自成体系,也就是说这些小系统可以拥有自己的数据库,框架甚至语言等,这些小系统通常以提供 Rest Api ...
- [转载] 构建微服务:使用API Gateway
原文: http://mp.weixin.qq.com/s?__biz=MzA5OTAyNzQ2OA==&mid=206889381&idx=1&sn=478ccb35294c ...
- Spring Boot中使用Swagger2构建API文档
程序员都很希望别人能写技术文档,自己却很不愿意写文档.因为接口数量繁多,并且充满业务细节,写文档需要花大量的时间去处理格式排版,代码修改后还需要同步修改文档,经常因为项目时间紧等原因导致文档滞后于代码 ...
随机推荐
- 第2-3-2章 环境搭建-文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss
目录 5. 文件服务开发 5.1 环境搭建 5.1.1 数据库环境搭建 5.1.2 Nacos环境搭建 5.1.3 Nginx环境搭建 5.1.4 maven工程环境搭建 5. 文件服务开发 全套代码 ...
- 谈软件-专家谈C/C++重构的操作与思路
1.Refactoring: 对软件内部结构的一种调整,目的是不该被软件的可观察行为的前提上,提高其可理解性,降低其修改成本. 2.代码坏味道 2.1.不易复用 2.2.不易理解 2.3.存在冗余 3 ...
- Kubernetes_Deployment全解析(无状态的Pod)
前言 一.创建Deployment 1.1 创建Deployment apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deploy ...
- Windows之应用安装程序 —— winget
大家都用过Linux中的应用程序安装工具,如yum.apt.rpm等工具进行安装自己想要的一些工具或则软件之类的,当然Linux操作系统还是很强大的有很多类似的命令来安装我们所需要的程序,但是wind ...
- 动态规划篇——线性DP
动态规划篇--线性DP 本次我们介绍动态规划篇的线性DP,我们会从下面几个角度来介绍: 数字三角形 最长上升子序列I 最长上升子序列II 最长公共子序列 最短编辑距离 数字三角形 我们首先介绍一下题目 ...
- 使用repo上传代码
前言~ repo是一款安卓用于管理源码的工具,由python实现,基于git工具 本文介绍了repo的常用使用方式. 一,下载代码 1. repo init 初始化命令 此命令常用选项就那几个,此处取 ...
- Pod控制器详解
Pod控制器详解 7.1 Pod控制器介绍 Pod是kubernetes的最小管理单元,在kubernetes中,按照pod的创建方式可以将其分为两类: 自主式pod:kubernetes直接创建出来 ...
- 【数据库】Postgresql、PG的分区操作:创建、删除指定分区,非分区表转分区表
〇.参考链接 一.为表创建指定分区 -- 表创建分区 参数 表名 分区序列 例如: ltc_customer , 20220915 则创建 ltc_customer_20220915 分区表 CREA ...
- PostgreSQL和MySQL的优劣对比
在开发项目的过程中,难免要面对选择数据库的情况.总结此文章是因为在之前公司里使用的都是MYSQL 数据库,而在现在公司里,新项目中使用的是 PostgreSQL 数据库,在使用过程中,经常需要查找两种 ...
- 深入理解Whitelabel Error Page底层源码
深入理解Whitelabel Error Page底层源码 (一)服务器请求处理错误则转发请求url StandardHostValve的invoke()方法将根据请求的url选择正确的Context ...