openwhisk-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Michele Sciabarra <>
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.


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:

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
  name: hellows
apiVersion: v1
kind: ConfigMap
  name: hellows
  namespace: hellows
  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
  name: hellows
  namespace: hellows
    app: hellows
  - name: mnt
      name: hellows
  - name: hellows
    image: actionloop/golang-v1.11:ws3
    - containerPort: 8080
      protocol: TCP
    - name: mnt
      mountPath: "/mnt"    
    - name: OW_WEBSOCKET
      value: /hello
    - name: OW_AUTOINIT
      value: /mnt/main.go
apiVersion: v1
kind: Service
  name: hellows
  namespace: hellows
  - port: 8080
    protocol: TCP
    targetPort: 8080
    app: hellows
apiVersion: extensions/v1beta1
kind: Ingress
  name: hellows
  namespace: hellows
  - host:
      - path: /hello
          serviceName: hellows
          servicePort: 8080

  Michele Sciabarra

View raw message