Go SDK for WebAssembly-based Envoy extensions
This project is in its early stage, and the API is likely to change and not stable.
The Go sdk for
proxy-wasm, enabling developers to write Envoy extensions in Go.
proxy-wasm-go-sdk is powered by TinyGo and does not support the official Go compiler.
import (
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
)
var counter proxywasm.MetricCounter
type metricRootContext struct { proxywasm.DefaultRootContext }
func (ctx *metricRootContext) OnVMStart(int) types.OnVMStartStatus {
// initialize the metric
counter = proxywasm.DefineCounterMetric("proxy_wasm_go.request_counter")
return types.OnVMStartStatusOK
}
type metricHttpContext struct { proxywasm.DefaultHttpContext }
func (ctx *metricHttpContext) OnHttpRequestHeaders(int, bool) types.Action {
// increment the request counter when we receive request headers
counter.Increment(1)
return types.ActionContinue
}
requirements
proxy-wasm-go-sdk depends on TinyGo's WASI (WebAssembly System Interface) target
which is introduced in v0.16.0.
Please follow the official instruction here.
compatible ABI / Envoy builds (verified on CI)
proxy-wasm-go-sdk |
proxy-wasm ABI version |
istio/proxyv2 |
Envoy upstream |
main |
0.2.0 |
1.8.1+ |
1.17.x |
v0.1.0 |
0.2.0 |
1.8.{1,2,3,4}, 1.9.{0,1} |
1.17.{0,1} |
run examples
build:
make build.examples # build all examples
make build.examples.docker # in docker
make build.example name=helloworld # build a specific example
make build.example.docker name=helloworld # in docker
run:
make run name=helloworld
sdk development
make test # run local tests without running envoy processes
## requires you to have Envoy binary locally
make test.e2e # run e2e tests
## requires you to have Envoy binary locally
make test.e2e.single name=helloworld # run e2e tests
limitations and considerations
- Some of existing libraries are not available (importable but runtime panic / non-importable)
- There are several reasons for this:
- TinyGo's WASI target does not support some of syscall: For example, we cannot import
crypto/rand
package.
- TinyGo does not implement all of reflect package(examples).
- proxy-wasm-cpp-host has not supported some of WASI APIs yet
(see the supported functions).
- These issues will be mitigated as TinyGo and proxy-wasm-cpp-host evolve.
- There's performance overhead of using Go/TinyGo due to GC
runtime.GC
is called whenever the heap runs out (see 1,
2).
- TinyGo allows us to disable GC, but we cannot do that since we need to use maps (implicitly causes allocation)
for saving the plugin's state.
- Theoretically, we can implement our own GC algorithms tailored for proxy-wasm through
alloc(uintptr)
interface
with -gc=none
option. This is the future TODO.
recover
is not implemented in TinyGo, and there's no way to prevent the WASM virtual machine from aborting.
- Goroutine support
- In Tinygo, Goroutine is implmeneted through LLVM's coroutine (see this blog post).
- In Envoy, WASM modules are run in the event driven manner, and therefore the "scheduler" is not executed once the main function exits.
That means you cannot have the expected behavior of Goroutine as in ordinary host environments.
- The question "How to deal with Goroutine in a thread local WASM VM executed in the event drive manner" has yet to be answered.
- We strongly recommend that you implement the
OnTick
function for any asynchronous task instead of using Goroutine.
- The scheduler can be disabled with
-scheduler=none
option of TinyGo.
references
Special thanks to TinyGo folks:)