A brief walkthrough
function (ctx, data) {}
A brief walkthrough
function (ctx, data) {}
tryAsync
// Async function
export const tryAsync = (ctx, data) => {
console.log('Data received: %o', data);
ctx.send(data);
};
// HTTP sync function
export const tryKnative = (req, res) => {
res.send(`Hello, ${req.query.u || 'World'}!`);
};
{
"main": "index.mjs",
"scripts": {
"start": "functions-framework --target=tryKnative"
},
"dependencies": {
"@openfunction/functions-framework": "^0.4.1"
}
}
package.json
, sciprts
and dependencies
sections could be omitted start
script is highly recommeneded for local developmentLocal build is recommended if your Kubernetes nodes have limited access to GitHub or Docker Hub.
Install Cloud Native Buildpacks project’s Pack CLI tool
Use pack
tool to build your function image at local [1]
pack build -B openfunction/builder-node:v2-16.13 \ # Builder image, `16` is the latest version
-e FUNC_NAME=tryKnative \ # Default entry point function
-p src \ # Path of source files to be built
<image-repo>/<image-name>:<tag>
Push function image to target container repository (e.g. Docker Hub)
docker push <image-repo>/<image-name>:<tag>
pack
tool would download builder image during the build process ↩︎
Use async function to bridge MQTT messages among topic channels
In this lab, we will use EMQX as the broker infrastructure. Learn full steps.
Add EMQX Helm Chart repository
helm repo add emqx https://repos.emqx.io/charts
helm repo update
Search available charts of EMQX
helm search repo emqx
NAME CHART VERSION APP VERSION DESCRIPTION
emqx/emqx 4.4.3 4.4.3 A Helm chart for EMQX
emqx/emqx-ee 4.4.3 4.4.3 A Helm chart for EMQ X
Deploy single replica of EMQX, and expose NodePort service
helm install emqx emqx/emqx --set replicaCount=1 --set service.type=NodePort
apiVersion: core.openfunction.io/v1beta1
kind: Function
metadata:
name: sample-node-async-bindings
spec:
version: v2.0.0
image: '<image-repo>/<image-name>:<tag>'
serving:
# default to knative
runtime: async
annotations:
# default to "grpc"
dapr.io/app-protocol: http
template:
containers:
- name: function
params:
# default to FUNC_NAME value
FUNCTION_TARGET: tryAsync
inputs:
- name: mqtt-input
component: mqtt-in
outputs:
- name: mqtt-output
component: mqtt-out
operation: create
bindings:
mqtt-in:
type: bindings.mqtt
version: v1
metadata:
- name: consumerID
value: '{uuid}'
- name: url
value: tcp://admin:public@emqx:1883
- name: topic
value: in
mqtt-out:
type: bindings.mqtt
version: v1
metadata:
- name: consumerID
value: '{uuid}'
- name: url
value: tcp://admin:public@emqx:1883
- name: topic
value: out
Apply function manifest, and check running states
$ kubectl apply -f async-bindings.yaml
function.core.openfunction.io/sample-node-async-bindings created
$ kubectl get fn
NAME BUILDSTATE SERVINGSTATE BUILDER SERVING URL AGE
sample-node-async-bindings Skipped Running serving-8f7xc 140m
$ kubectl get po
NAME READY STATUS RESTARTS AGE
serving-8f7xc-deployment-v200-l78xc-564c6b5bf7-vksg7 2/2 Running 0 141m
Furthermore, check whether function
container output correct logs
$ kubectl logs -c function serving-8f7xc-deployment-v200-l78xc-564c6b5bf7-vksg7
...
[Dapr-JS] Listening on 8080
[Dapr-JS] Letting Dapr pick-up the server (Maximum 60s wait time)
[Dapr-JS] - Waiting till Dapr Started (#0)
[Dapr-JS] Server Started
See also: MQTT X desktop client
Connect EQMX server via NodePort mapped to tcp:1883
Publish {"msg": "hello"}
to in
topic
out
topic 👇 👉Check the function
container log
$ kubectl logs -c function serving-8f7xc-deployment-v200-l78xc-564c6b5bf7-vksg7
...
[Dapr-JS] Listening on 8080
[Dapr-JS] Letting Dapr pick-up the server (Maximum 60s wait time)
[Dapr-JS] - Waiting till Dapr Started (#0)
[Dapr-JS] Server Started
Data received: { msg: 'hello' }
apiVersion: core.openfunction.io/v1beta1
kind: Function
metadata:
name: sample-node-async-pubsub
spec:
version: v2.0.0
image: '<image-repo>/<image-name>:<tag>'
serving:
# default to knative
runtime: async
annotations:
# default to "grpc"
dapr.io/app-protocol: http
template: ...
params:
# default to FUNC_NAME value
FUNCTION_TARGET: tryAsync
inputs:
- name: mqtt-sub
component: mqtt-pubsub
topic: sub
outputs:
- name: mqtt-pub
component: mqtt-pubsub
topic: pub
pubsub:
mqtt-pubsub:
type: pubsub.mqtt
version: v1
metadata:
- name: consumerID
value: '{uuid}'
- name: url
value: tcp://admin:public@emqx:1883
- name: qos
value: 1
Apply function manifest, and check running states
$ kubectl apply -f async-pubsub.yaml
function.core.openfunction.io/sample-node-async-pubsub created
$ kubectl get fn
NAME BUILDSTATE SERVINGSTATE BUILDER SERVING URL AGE
sample-node-async-pubsub Skipped Running serving-2qfkl 140m
$ kubectl get po
NAME READY STATUS RESTARTS AGE
serving-2qfkl-deployment-v200-6cshf-57c8b5b8dd-ztmbf 2/2 Running 0 141m
Furthermore, check whether function
container output correct logs
$ kubectl logs -c function serving-2qfkl-deployment-v200-6cshf-57c8b5b8dd-ztmbf
...
[Dapr-JS] Listening on 8080
[Dapr-JS] Letting Dapr pick-up the server (Maximum 60s wait time)
[Dapr-JS] - Waiting till Dapr Started (#0)
[Dapr API][PubSub] Registered 1 PubSub Subscriptions
[Dapr-JS] Server Started
Connect EQMX server via NodePort mapped to tcp:1883
Publish a CloudEvents event to pub
topic
sub
👉Check the function
container log
$ kubectl logs -c function serving-2qfkl-deployment-v200-6cshf-57c8b5b8dd-ztmbf
...
[Dapr-JS] Listening on 8080
[Dapr-JS] Letting Dapr pick-up the server (Maximum 60s wait time)
[Dapr-JS] - Waiting till Dapr Started (#0)
[Dapr API][PubSub] Registered 1 PubSub Subscriptions
[Dapr-JS] Server Started
Data received: { orderId: '100' }