The objective of this document is to explain the basic concepts a developer needs to understand in order to use with WebAssembly to create microservices that run under edgeEngine.
The intended readers of this document are developers who have a working knowledge of programming a microservice targeted to an instance of edgeEngine running on a remote device. Also, the intended reader needs to have a basic understanding of how to create and use WebAssembly binaries.
In order to get the full benefit from reading this document, the intended reader needs to:
After reading this document, you will:
According to WebAssembly.org, "WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications."
WebAssembly is an open source specification. Thus, developers can write WebAssembly binaries in a low-level language such as C++ or Rust. WebAssembly is not intended to work with any language that uses a runtime interpreter, as you find in Python or Node.js. Rather, the WebAssembly binary is similar to Java byte code in that it is run against a special intermediary very similar to a Just In Time (JIT) compiler. As long as your language of choice can output code to a WASM binary, it will be supported under WebAssembly. Thus you can even write code in TypeScript because the AssemblyScript compiler will transform the TypeScript to a WASM binary.
In short, WebAssembly allows developers to create easily transportable binaries written according to the standard WASM specification. As a result, developers can create binary deployment units that are small and fast.
WebAssembly allows developers to create code which is organized under WASM using the term module. WebAssembly modules have the ability to utilize a machine’s pure compute power.
This emphasis on pure compute power is important because, many times the rate at which calculations can be performed using WebAssembly is significantly faster than high level alternatives. When a module needs to have capabilities beyond that of increased compute power, for example, trying to access the contents of a file then an implementation-specific WASM Application Binary Interface (ABI) implementation is required.
The Application Binary Interface (ABI) is an interface between two binary program modules. Under the mimik implementation of WebAssembly, ABI is the way WebAssembly Modules interact with the host system.
Presently the ABI specification published by the WebAssembly committee is the WebAssembly System Interface (WASI). (WASI) allows the WASM module to utilize the host environment to access the file system, clock, etc. ( Please note that the ability to work with sockets is not finalized into WASI.)
At the present time, mimik publishes an SDK that supports mimik serverless WebAssembly ABI for C++. This WASM Serverless ABI is defined and implemented by mimik in order to give the WASM module the ability to access the mimik edgeEngine microservice serverless environment.
In addition to allowing WASM modules to utilize the mimik serverless environment, supporting the WASM ABI allows developers to create powerful edge microservices that work directly with the host system; for example, implementing a RESTful API that has the ability to extract data stored in log files that are part of the host machine's file system.
Under edgeEngine, a developer creates and compiles the WebAssembly (WASM) binary on a development machine. That binary gets embedded into a .tar file as part of the edgeEngine microservice development process. That .tar file is the deployment unit that's sent onto the (remote) device running edgeEngine.
There's a small amount of work that needs to be done on the remote device to deploy the tar file as a microservice. If a developer is creating microservices targeted at an iOS or Android device, the respective mimik mobile SDK streamlines the deployment process within the remote device. For desktop computers and smaller Raspberry Pi machines, the deployment process is done using the edgeEngine CLI tool.
Figure 1 below describes how a microservice written into a WebAssembly binary interacts with a device's instance of edgeEngine.
The paragraphs that follow describe the design in detail.
The key to understanding how WebAssembly integrates into mimik's edgeEngine architecture is to remember that edgeEngine (callout 2 in Figure 1 above) is intended to run as the sole provider of access to all microservices running on a remote device (callout 1) or standalone computer. As such, when developers deploy a WebAssembly binary on a device, the deployment process registers the microservice within the WebAssembly binary with edgeEngine (callout 3) thus giving that microservice access to the resources that edgeEngine provides, particularly the Universal Web Server (callout 5). For all intents and purposes, the Universal Web Server provides a "serverless" runtime environment for edgeEngine microservices. A microservice does not need to provide its own HTTP server to support its underlying REST API. The Universal Web Server does it all on behalf of all microservices.
However, a WebAssembly binary still needs to do the work of providing the API endpoint definitions and associated processing logic for the microservice (callout 4). Creating the API endpoint definitions and processing logic is the programming work done by developers.
Once a WebAssembly binary is deployed to a remote device or compute, the API embedded within the binary is exposed by the edgeEngine Universal Web Server. That API is then accessible to other devices (callout 6) via HTTP as a typical REST service represented by a URL that is special to the remote device hosting the WebAssembly binary.