Open illume opened 6 months ago
So far, my findings on the issue have been this.
Create a Function to Open a New Websocket Connection to the Cluster from the Backend:
We can use the gorilla/websocket
package to handle websocket connections. We can create a function like openWebsocketConnectionToCluster
that utilizes this package to establish a websocket connection to the Kubernetes cluster. This function would typically involve upgrading an HTTP connection to a websocket connection using the Upgrade
method provided by the gorilla/websocket
package.
import "github.com/gorilla/websocket"
func openWebsocketConnectionToCluster(clusterURL string) (*websocket.Conn, error) {
// Dial websocket connection to the cluster URL
conn, _, err := websocket.DefaultDialer.Dial(clusterURL, nil)
if err != nil {
return nil, err
}
return conn, nil
}
Create a Map to Store Active Websocket Connections: We can use a map to store active websocket connections, where the keys are the URLs or anything unique like userID + clustername + url of the clusters and the values are the websocket connections.
var activeConnections = make(map[string]*websocket.Conn)
Create a New Websocket Endpoint in the Backend (/websocket):
We would create a new route handler for the /websocket
endpoint. This handler would upgrade incoming HTTP requests to websocket connections.
func websocketHandler(w http.ResponseWriter, r *http.Request) {
// Upgrade HTTP connection to websocket
conn, err := websocket.Upgrade(w, r, nil, 1024, 1024)
if err != nil {
http.Error(w, "Could not upgrade to websocket", http.StatusBadRequest)
return
}
// Handle websocket connection
// (Code for handling connection would typically go here)
}
func main() {
http.HandleFunc("/websocket", websocketHandler)
}
Frontend Makes a Request to the Backend Websocket Endpoint:
From the frontend, we would make an HTTP request to the /websocket
endpoint of the backend server.
Upgrade the Request:
Upon receiving the HTTP request at the /websocket
endpoint, the backend server automatically upgrades the connection to a websocket connection using the Upgrade
method provided by the gorilla/websocket
package.
Frontend Sends Cluster Name and URL: As part of the HTTP request payload or query parameters, the frontend includes the cluster name and URL to which it wants to connect.
Backend Checks Map for Existing Websocket Connection to That URL:
The backend server retrieves the cluster URL from the request and checks the activeConnections
map to determine if there is already an established connection to that URL.
If Connection Exists, Use It; Otherwise, Create and Store It in the Map:
If a websocket connection to the specified URL already exists in the activeConnections
map, the backend server reuses that connection. Otherwise, it invokes the openWebsocketConnectionToCluster
function to establish a new connection and stores it in the activeConnections
map, associating it with the provided cluster URL.
Once the Connection from Backend to Cluster Is Made, Listen Continuously and Send All the Responses to the Frontend: After establishing the websocket connection to the Kubernetes cluster from the backend, the backend server enters a loop where it continuously listens for incoming messages or events from the cluster. As messages arrive, the backend server forwards them to the frontend through the established websocket connection.
I think we can efficiently manage multiple websocket connections to Kubernetes clusters, ensuring seamless communication between the frontend and the clusters while minimizing resource usage and overhead.
WDTY cc @illume?
For 2,
there is going to be one web socket connection right? In this case it does not make sense to me that there is a cluster name used as a key.
Other than those two points I’m not sure of it looks good to me.
For 2,
there is going to be one web socket connection right? In this case it does not make sense to me that there is a cluster name used as a key.
Yes only 1 connection would be there. We will use combination of something unique like userID + clustername + url
- This will need to make sure all data matches before reuse. What happens if a connection without a token reuses one with one? So there needs to be some checks that all parameters for the connection are the same before reusing a connection.
yes, good catch. Will think of something regarding this too.
In https://github.com/headlamp-k8s/headlamp/issues/1373 we investigated websocket pool max limit that browsers have. Which we quickly encounter.
One solution to this problem is to have a backend service which takes one websocket from the browser and makes multiple websocket connections via the backend to kubernetes API server.
We already use the backend server to proxy K8s API requests.
Architecture diagram:
Some related websocket links to multi plexing and proxying