A template project to demonstrate how to run WebAssembly functions as sidecar microservices in dapr

Overview

Demo and tutorials

Live Demo | Tutorial article | Tutorial video

1. Introduction

DAPR is a portable, event-driven runtime that makes it easy for any developer to build resilient, stateless and stateful applications that run on the cloud and edge and embraces the diversity of languages and developer frameworks. It's a Microsoft-incubated open-source project.

WasmEdge is a open-source, high-performance, extensible, and hardware optimized WebAssembly Virtual Machine for automotive, cloud, AI, and blockchain applications.

In this demonstration App, we create two image processing web services, integrated with Dapr. This project is built to demonstrate how to use Dapr to integrate Web applications in any programming language, and how WasmEdge can be embed in Go and Rust applications.

2. Architecture

This project contains 4 Dapr sidecar services:

It is a simple Go Web application which is exposed as an endpoint of the whole application. It will render a static HTML page for the user to upload an image, and receive the image from the user, redirect request to internal image APIs.

This Dapr service is written in Rust and compiled to WebAssembly. Running inside WasmEdge Runtime, the WebAssembly bytecode program creates a HTTP service that listens for RPC requests from other Dapr applications, including the web port.

This Dapr service is written in Golang. It uses WASI to call a prebuild wasm file to classify an image using a Tensorflow model.

This Dapr service is written in Rust. It simply starts a new process for the WasmEdge VM to run and perform grayscale on a image.

doc

3. Prerequisites

4. Build

make pre-install  ## Install WasmEdge dependences
make build        ## Will build all the components

## If you modify the wasm functions project,
## Use the commands in ./functions/grayscale/build.sh 
## and ./functions/classify/build.sh to generate new compiled files
make build-wasm

5. Run

To simplify the deployment, we provide a script to run the services:

make run-api-wasi-socket-rs ## Run the WasmEdge microservice
make run-api-go ## Run the image-api-go microservice
make run-api-rs ## Run the image-api-rs microservice
make run-web ## Run the Web port service

For each component, you can also run it individually:

Start the web-port service

cd web-port
dapr run --app-id go-web-port \
         --app-protocol http \
         --app-port 8080 \
         --dapr-http-port 3500 \
         --components-path ../config \
         --log-level debug \
         ./web-port

Start the WasmEdge microservice for image processing

cd image-api-wasi-socket-rs
dapr run --app-id image-api-wasi-socket-rs \
         --app-protocol http \
         --app-port 9005 \
         --dapr-http-port 3503 \
         --components-path ../config \
         --log-level debug \
	 wasmedge ./target/wasm32-wasi/debug/image-api-wasi-socket-rs.wasm
cd image-api-go
dapr run --app-id image-api-go \
         --app-protocol http \
         --app-port 9003 \
         --dapr-http-port 3501 \
         --log-level debug \
         --components-path ../config \
         ./image-api-go

Start the image-api-rust service

cd image-api-rs
dapr run --app-id image-api-rs \
         --app-protocol http \
         --app-port 9004 \
         --dapr-http-port 3502 \
         --components-path ../config \
         --log-level debug \
         ./target/debug/image-api-rs

After all the services started, we can use this command to verify:

dapr list
  APP ID                     HTTP PORT  GRPC PORT  APP PORT  COMMAND               AGE  CREATED              PID
  go-web-port                3500       44483      8080      ./web-port            15m  2021-10-23 12:19.59  270961
  image-api-wasi-socket-rs   3503       41775      9005      wasmedge              9m   2021-10-23 12:25:27  294758
  image-api-rs               3502       41661      9004      ./target/release/...  9m   2021-10-23 12:25.27  285749
  image-api-go               3501       34291      9003      ./image-api-go        9m   2021-10-23 12:25.27  285852

6. Online Demo: Dapr-WasmEdge

Access the demo here

Comments
  • Create WasmEdge HTTP server sidecars

    Create WasmEdge HTTP server sidecars

    We would like to create two sidecars that are just wasmedge or wasmedge-tensorflow-lite. Instead of using GO or Rust to implement HTTP servers and then bootstrap wasmedge, we would just run those wasmedge-based server apps in sidecars.

    Sidecar #1: implement the grayscale function in Rust.

    https://github.com/second-state/wasmedge_wasi_socket/tree/main/examples/http_server

    Sidecar #2: implement the tensorflow function in JS

    https://github.com/second-state/wasmedge-quickjs#http-request

    https://github.com/second-state/wasmedge-quickjs#tensorflow

    https://www.secondstate.io/articles/embed-javascript-in-rust/

    After that, modify the web port to show all 4 sidecar apps.

    opened by juntao 15
  • It seems that memory leak occurs when image-api-go is called.

    It seems that memory leak occurs when image-api-go is called.

    I replace the web-port imageHandler func with the following code, to make it easier to observe(making more requests on one click). The memory usage of image-api-go is keeping growing when click classify.

    type mock struct {}
    
    func (m *mock)WriteHeader(statusCode int) {
    }
    
    func (m *mock)Header() http.Header {
    	return nil
    }
    func (m *mock)Write(b []byte) (int, error) {
    	return len(b), nil
    }
    
    func imageHandler(w http.ResponseWriter, r *http.Request) {
    	println("imageHandler ....")
    	body, err := ioutil.ReadAll(r.Body)
    
    	if err != nil {
    		println("error: ", err.Error())
    		panic(err)
    	}
    	api := r.Header.Get("api")
    	if api == "go" {
    		daprClientSend(body, w)
    		for i:=0;i<10;i++ {
    			go func() {
    				for i:=0;i<10;i++ {
    					daprClientSend(body, &mock{})
    				}
    			}()
    		}
    	} else {
    		httpClientSend(body, w)
    	}
    }
    
    opened by Taction 6
  • Use wasmedge-bindgen instead of wasm-bindgen in the GO SDK example

    Use wasmedge-bindgen instead of wasm-bindgen in the GO SDK example

    The current example uses wasm-bindgen to pass call parameters from the GO app to the WASM function. However, wasm-bindgen does not work with the Rust WASI target since Rust version 1.51. We now have a better solution for bindgen since WasmEdge 0.9.0. It is called wasmedge-bindgen:

    https://wasmedge.org/book/en/embed/go/function.html

    Can we refactor the GO host example to use wasmedge-bindgen?

    opened by juntao 5
  • Image formats

    Image formats

    The grayscale service only supports the GIF and PNG formats. But the classify service only supports the JPG format. Can we make them consistent?

    Perhaps supports JPGs by default in both services? Thanks.

    opened by juntao 4
  • GitHub Pages

    GitHub Pages

    I have configured GitHub Pages to serve from the main branch's root directory. So, our static web page is now available here:

    https://second-state.github.io/dapr-wasm/web/

    We do not actually need a GitHub Action for this. As soon as we update the main branch, it will be automatically deployed.

    We could, however, to use GitHub Actions to copy just the /web folder to another branch (e.g., gh-pages) and then deploy the gh-pages branch as the web site's root.

    opened by juntao 4
  • Create a customized WasmEdge for dapr

    Create a customized WasmEdge for dapr

    The WasmEdge GO SDK allows developers to register host functions to the runtime, and create a customized version of WasmEdge that includes the host functions.

    We should add Dapr GO SDK functions into a customized version of WasmEdge.

    We should then create Rust APIs for those Dapr host functions so that WasmEdge app developers can use them.

    opened by juntao 3
  • Error: error getting topics from app - unexpected end of JSON input - error occurred while beginning pubsub messages

    Error: error getting topics from app - unexpected end of JSON input - error occurred while beginning pubsub messages

    Hi,

    I am performing the grayscale tutorial example i.e. make run-api-rs the following error is occurring.

    ERRO[0000] error getting topics from app: unexpected end of JSON input  app_id=image-api-rs instance=wasm-oci-demo scope=dapr.runtime type=log ver=1.4.2
    ERRO[0000] error occurred while beginning pubsub messages: error getting topics from app: unexpected end of JSON input  app_id=image-api-rs instance=wasm-oci-demo scope=dapr.runtime type=log ver=1.4.2
    INFO[0000] dapr initialized. Status: Running. Init Elapsed 9.416037000000001ms  app_id=image-api-rs instance=wasm-oci-demo scope=dapr.runtime type=log ver=1.4.2
    

    The following video (which starts just as the error occurs) demonstrates the above error in action.

    https://youtu.be/A5EhO7cNTCw?t=392

    It seems that dapr list is displaying the correct output (in terms of apps, ports etc.)

    wasmedge@wasm-oci-demo:~$ dapr list
      APP ID        HTTP PORT  GRPC PORT  APP PORT  COMMAND               AGE  CREATED              PID     
      go-web-port   3500       40659      8080      ./web-port            36s  2021-10-05 02:38.25  334410  
      image-api-rs  3502       34493      9004      ./target/debug/im...  23s  2021-10-05 02:38.38  334530  
      image-api-go  3501       40639      9003      ./image-api-go        9s   2021-10-05 02:38.52  334658 
    

    Is it possible that the grayscale needs to be added to the config i.e. https://github.com/second-state/dapr-wasm/blob/main/config/conf.json

    Any suggestions would be greatly appreciated.

    Thanks Tim

    opened by tpmccallum 2
  • update wasmedge_wasi_socket version to 0.2.0

    update wasmedge_wasi_socket version to 0.2.0

    reoslve Mismatched function type. Expected: FuncType {params{i32 , i32 , i32} returns{i32}} , Got: FuncType {params{i32 , i32} returns{i32}} issue: #25

    opened by marviniter 1
  • Seems the wasm file is missed

    Seems the wasm file is missed

    https://github.com/second-state/dapr-wasm/blob/main/image-api-go/image_api.go#L50 The resource loaded seems not exist. Besides would you mind provide the code before compiling into wasm?

    opened by Taction 1
  • Inconsistent document/webpage link to this repo

    Inconsistent document/webpage link to this repo

    I see there are multiple article link to this repo with obsolete information: https://www.infoq.com/articles/webassembly-dapr-wasmedge/?utm_source=email&utm_medium=Web-Development&utm_campaign=newsletter&utm_content=11162021 https://wasmedge.org/book/en/use_cases/frameworks/mesh/dapr.html

    It seems above links are having a Golang microservice, I think it's better if you can maintain both repo or update again the article. Thanks

    opened by TanNgocDo 1
Owner
Second State
Fast, safe, portable & serverless. Deploy Rust functions in edge computing, Jamstack, SaaS and service mesh applications.
Second State
A template for kick starting a Rust and WebAssembly project using wasm-pack.

A template for kick starting a Rust and WebAssembly project using wasm-pack.

Haoxi Tan 1 Feb 14, 2022
🚀Wasmer is a fast and secure WebAssembly runtime that enables super lightweight containers to run anywhere

Wasmer is a fast and secure WebAssembly runtime that enables super lightweight containers to run anywhere: from Desktop to the Cloud, Edge and IoT devices.

Wasmer 14.1k Jan 8, 2023
A prototype WebAssembly linker using module linking.

WebAssembly Module Linker Please note: this is an experimental project. wasmlink is a prototype WebAssembly module linker that can link together a mod

Peter Huene 19 Oct 28, 2022
Sealed boxes implementation for Rust/WebAssembly.

Sealed boxes for Rust/WebAssembly This Rust crate provides libsodium sealed boxes for WebAssembly. Usage: // Recipient: create a new key pair let reci

Frank Denis 16 Aug 28, 2022
WebAssembly on Rust is a bright future in making application runs at the Edge or on the Serverless technologies.

WebAssembly Tour WebAssembly on Rust is a bright future in making application runs at the Edge or on the Serverless technologies. We spend a lot of ti

Thang Chung 129 Dec 28, 2022
WebAssembly modules that use Azure services

This is an experimental repository containing WebAssembly modules running on top of WAGI (WebAssembly Gateway Interface, which allows you to run WebAssembly WASI binaries as HTTP handlers) and using Azure services.

null 7 Apr 18, 2022
WebAssembly Service Porter

WebAssembly Service Porter.

henrylee2cn 12 Dec 12, 2022
WAGI: WebAssembly Gateway Interface

Write HTTP handlers in WebAssembly with a minimal amount of work

null 724 Jan 6, 2023
A console and web-based Gomoku written in Rust and WebAssembly

?? rust-gomoku A console and web-based Gomoku written in Rust and WebAssembly Getting started with cargo & npm Install required program, run # install

namkyu1999 2 Jan 4, 2022
WebAssembly development with Trunk & Vite.js

Trunk & Vite.js Demo Trunk is a WASM web application bundler for Rust, and Vite.js is next Generation Frontend Tooling. Ok, they are together now for

Libing Chen 6 Nov 24, 2021
darkforest is a console and web-based Roguelike written in Rust and WebAssembly.

darkforest darkforest is a console and web-based Roguelike written in Rust and WebAssembly. Key Features TBA Quick Start TBA How To Contribute Contrib

Chris Ohk 5 Oct 5, 2021
WebAssembly to Lua translator, with runtime

This is a WIP (read: absolutely not ready for serious work) tool for translating WebAssembly into Lua. Support is specifically for LuaJIT, with the se

null 43 Dec 31, 2022
A Rust ESP stack trace decoder that can also runs in your browser thanks to WebAssembly

ESP Stack Trace Decoder A Rust ESP stack trace decoder that can also runs in your browser thanks to WebAssembly. It is composed of a ⌨️ Rust library,

Maxime BORGES 20 Oct 5, 2022
Simple file sharing with client-side encryption, powered by Rust and WebAssembly

Hako Simple file sharing with client-side encryption, powered by Rust and WebAssembly Not feature-packed, but basic functionalities are just working.

Jaehyeon Park 30 Nov 25, 2022
bn.js bindings for Rust & WebAssembly with primitive-types support

bn.rs bn.js bindings for Rust & WebAssembly with primitive-types support Write Rust code that uses BN use std::str::FromStr; use primitive_types::{H1

Alexey Shekhirin 23 Nov 22, 2022
A handy calculator, based on Rust and WebAssembly.

qubit ?? Visit Website To Use Calculator Example ?? Visit Website To Use Calculator 2 + 2

Abhimanyu Sharma 55 Dec 26, 2022
A simple compile-to-WebAssembly language rewritten in Rust

chasm A very simple compile-to-WebAssembly language You can play with chasm online. This is a rewrite in Rust of the compiler for the language chasm.

null 11 Nov 27, 2022
Webassembly binding for Hora Approximate Nearest Neighbor Search Library

hora-wasm [Homepage] [Document] [Examples] [Hora] Javascript bidding for the Hora Approximate Nearest Neighbor Search, in WebAssembly way. Features Pe

Hora-Search 26 Sep 23, 2022
Stylist is a CSS-in-Rust styling solution for WebAssembly Applications.

Stylist Stylist is a CSS-in-Rust styling solution for WebAssembly Applications. This is a fork of css-in-rust. Install Add the following to your Cargo

Kaede Hoshikawa 190 Dec 30, 2022