openwhisk-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Michele Sciabarra <mich...@sciabarra.com>
Subject [Long] I implemented websocket support for the Golang and related runtimes:
Date Thu, 17 Jan 2019 18:07:42 GMT
Hello whiskers!

Sorry it is a bit long, so I split it into parts with headlines.

TL;DR

I implemented support for Websocket so you can deploy an Action as a WebSocket server if you
have a Kubernetes cluster (or just a Docker server). See at the end of this post for an example
of a Kubernetes deployment descriptor.

Here is a very simple demo using it:

    https://hellows.sciabarra.net/

It uses a websocket server implemented using the golang runtime and the code of an UNCHANGED
OpenWhisk action. All the magic happens at deployment using the descriptor provided.

I believe it is a good foundation for implementing websocket support in OpenWhisk. The next
step would be to provide support at the API level. 

After reading the rest, the question is: does the community approve this feature? If yes,
I can submit a PR for including it in the next release of the actionloop.

1. Motivation: why I did this

A few days ago I asked what was the problem in having an action that creates a persistent
connection to Kafka. I was answered that a Serverless environment can flood Kafka with requests
because more actions are spawn when the load increase.

The solution is to create a separate server to be deployed somewhere, for example, Kubernetes,
maybe using WebSockets to communicate with Kafka. In short, I had the need to transform an
action in a WebSocket server.

Hence I had the idea of adding WebSocket support to Action as WebSocket server, adding support
for WebSocket to ActionLoop, so I could create a WebSocket server in the same way as you write
an action. 

2. What I did

I implemented WebSocket support in the action runtime. If you deploy the action now it answers
not only to `/run` but also to `/ws` (it is configurable) as a WebSocket in continuous mode.

You enable the WebSocket setting the environment variable OW_WEBSOCKET. Also, for the sake
of easy deployment, there is also now an autoinit feature. If you set the environment variable
to OW_AUTOINIT, it will initialize the runtime from the file you specified in the variable.

Ok, fine you can say, but how can I use it?

With a Kubernetes descriptor! You can launch the runtime in Kubernetes, provide the main action
in it (you can also download it from a git repo or store in a volume), and now your action
is a web socket server answering to your requests.

Look to the following descriptor for an example:

It is a bit long, this is what it does

- it creates a configmap containing the action code
- it launches the image mounting the action code
- the image initialize the action and then listen to the WebSocket 
- the image also exposes the web socket using an ingress


apiVersion: v1
kind: Namespace
metadata:
  name: hellows
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: hellows
  namespace: hellows
data:
  main.go: |
    package main
    import "fmt"
    func Main(obj map[string]interface{}) map[string]interface{} {
      name, ok := obj["name"].(string)
      if !ok { 
        name = "world" 
      }
      fmt.Printf("name=%s\n", name)
      msg := make(map[string]interface{})
      msg["golang-main-single"] = "Hello, " + name + "!"
      return msg 
    }
---
apiVersion: v1
kind: Pod
metadata:
  name: hellows
  namespace: hellows
  labels:
    app: hellows
spec:
  volumes:
  - name: mnt
    configMap:
      name: hellows
  containers:
  - name: hellows
    image: actionloop/golang-v1.11:ws3
    ports:
    - containerPort: 8080
      protocol: TCP
    volumeMounts:
    - name: mnt
      mountPath: "/mnt"    
    env:
    - name: OW_WEBSOCKET
      value: /hello
    - name: OW_AUTOINIT
      value: /mnt/main.go
---
apiVersion: v1
kind: Service
metadata:
  name: hellows
  namespace: hellows
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: hellows
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hellows
  namespace: hellows
spec:
  rules:
  - host: hellows.sciabarra.net
    http:
      paths:
      - path: /hello
        backend:
          serviceName: hellows
          servicePort: 8080


-- 
  Michele Sciabarra
  michele@sciabarra.com

Mime
View raw message