openwhisk-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Carlos Santana <csantan...@gmail.com>
Subject Re: [Long] I implemented websocket support for the Golang and related runtimes:
Date Mon, 21 Jan 2019 17:37:05 GMT
Hi Michele this looks very cool in deed

Where you able to create a container in k8s with a main.go that took
websocket input and output to a persistent kafka connection

I'm interested in this as I have a use case that I want IBM Cloud Function
to ingest into kafka, and I was going to build similar thing as you did
using http 1or 2 server, that then ingest into kafka as a service (Event
Streams).
I was going to deploy this container into kubernetes, but I wanted the
container to scale down to zero using Knative.

You have such main.go for your runtime with websocket at one side and kafka
producer at the other?

-- Carlos

On Thu, Jan 17, 2019 at 1:07 PM Michele Sciabarra <michele@sciabarra.com>
wrote:

> 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
>


-- 
Carlos Santana
<csantana23@gmail.com>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message