websockets-go

module
v0.0.0-...-5808d0b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 5, 2024 License: Apache-2.0

README

WebSocket - Go

A simple WebSocket server that performs the HTTP upgrade and prints log messages on all standardized WebSocket events, such as open, message, close and error. The server is written in Golang and uses the Gorilla WebSocket library.

Before you begin

  • A Kubernetes cluster with Knative installed and DNS configured. See Install Knative Serving.
  • ko or Docker installed and running on your local machine, and a Docker Hub account configured (we'll use it for a container registry).

The sample code.

  1. If you look in cmd/server/main.go, you will the main function setting a handleWebSocket function and starting the web server on the /ws context:

     func main() {
         http.HandleFunc("/ws", handleWebSocket)
         fmt.Println("Starting server on :8080...")
         if err := http.ListenAndServe(":8080", nil); err != nil {
             log.Fatalf("Server error: %v", err)
         }
     }
    
  2. The handleWebSocket performs the protocol upgrade and assigns various websocket handler functions, such as OnOpen or OnMessage:

     func handleWebSocket(w http.ResponseWriter, r *http.Request) {
         conn, err := upgrader.Upgrade(w, r, nil)
         if err != nil {
             log.Printf("Error upgrading to websocket: %v", err)
             return
         }
         handlers.OnOpen(conn)
    
         go func() {
             defer handlers.OnClose(conn)
             for {
                 messageType, message, err := conn.ReadMessage()
                 if err != nil {
                     handlers.OnError(conn, err)
                     break
                 }
                 handlers.OnMessage(conn, messageType, message)
             }
         }()
     }
    
  3. The WebSocket application logic is located in the pkg/handlers/handlers.go file and contains callbacks for each WebSocket event:

     func OnOpen(conn *websocket.Conn) {
         log.Printf("WebSocket connection opened: %v", conn.RemoteAddr())
     }
    
     func OnMessage(conn *websocket.Conn, messageType int, message []byte) {
         log.Printf("Received message from %v: %s", conn.RemoteAddr(), string(message))
    
         if err := conn.WriteMessage(messageType, message); err != nil {
             log.Printf("Error sending message: %v", err)
         }
     }
    
     func OnClose(conn *websocket.Conn) {
         log.Printf("WebSocket connection closed: %v", conn.RemoteAddr())
         conn.Close()
     }
    
     func OnError(conn *websocket.Conn, err error) {
         log.Printf("WebSocket error from %v: %v", conn.RemoteAddr(), err)
     }
    

Build the application

Dockerfile
  • If you look in Dockerfile, you will see a method for pulling in the dependencies and building a small Go container based on Alpine. You can build and push this to your registry of choice via:
# Build and push the container on your local machine.
docker buildx build --platform linux/arm64,linux/amd64 -t "<image>" --push .
ko
  • You can use ko to build and push just the image with:
ko publish github.com/knative/docs/code-samples/serving/websockets-go

However, if you use ko for the next step, this is not necessary.

Deploy the application

yaml (with Dockerfile)
  • If you look in service.yaml, take the <image> name you used earlier and insert it into the image: field, then run:
kubectl apply -f config/service.yaml
yaml (with ko)
  • If using ko to build and push:
ko apply -f config/service.yaml

Testing the WebSocket server

Get the URL for your Service with:

kubectl get ksvc
NAME               URL                                                  LATESTCREATED             LATESTREADY              READY   REASON
websocket-server   http://websockets-server.default.svc.cluster.local   websockets-server-00001   websocket-server-00001   True

Now run a container with the wscat CLI and point it to the WebSocket application ws://websocket-server.default.svc.cluster.local/ws, like:

kubectl run --rm -i --tty wscat --image=monotykamary/wscat --restart=Never -- -c ws://websockets-server.default.svc.cluster.local/ws

Afterward you can chat with the WebSocket server like:

```If you don't see a command prompt, try pressing enter.
```connected (press CTRL+C to quit)
```> Hello
```< Hello
```>

The above is scaling to exactly one pod, since only one client was connected. Since Knative Serving allows you a dynamic scalling, a certain number of concurrent connections lead to a number of pods.

NOTE: Depending on the target annotation you have (autoscaling.knative.dev/target) you can scale based on num of connections.

Directories

Path Synopsis
cmd
pkg

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL