Convert Figma logo to code with AI

eranyanay logo1m-go-websockets

handling 1M websockets connections in Go

5,777
617
5,777
4

Top Related Projects

6,094

Tiny WebSocket library for Go.

Real-time messaging library for Go. The simplest way to add feature-rich and scalable WebSocket support to your application. The core of Centrifugo server.

Turn any program that uses STDIN/STDOUT into a WebSocket server. Like inetd, but for WebSockets.

Quick Overview

The "1m-go-websockets" repository is a demonstration project showcasing the ability to handle one million WebSocket connections in Go. It provides a simple implementation of a WebSocket server and client, along with benchmarking tools to test the scalability of WebSocket connections.

Pros

  • Demonstrates Go's efficiency in handling a large number of concurrent WebSocket connections
  • Includes both server and client implementations for comprehensive testing
  • Provides benchmarking tools to measure performance
  • Simple and easy-to-understand codebase for learning purposes

Cons

  • Not intended for production use, as it's primarily a demonstration project
  • Limited functionality beyond establishing and maintaining connections
  • Lacks advanced features like message routing or connection management
  • May require significant system resources to run at full scale

Code Examples

  1. Creating a WebSocket server:
func main() {
    http.HandleFunc("/ws", handleConnections)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

func handleConnections(w http.ResponseWriter, r *http.Request) {
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer ws.Close()

    for {
        messageType, p, err := ws.ReadMessage()
        if err != nil {
            return
        }
        if err := ws.WriteMessage(messageType, p); err != nil {
            return
        }
    }
}
  1. Creating a WebSocket client:
func main() {
    url := "ws://localhost:8080/ws"
    c, _, err := websocket.DefaultDialer.Dial(url, nil)
    if err != nil {
        log.Fatal("dial:", err)
    }
    defer c.Close()

    for {
        err := c.WriteMessage(websocket.TextMessage, []byte("Hello, Server!"))
        if err != nil {
            log.Println("write:", err)
            return
        }
        _, message, err := c.ReadMessage()
        if err != nil {
            log.Println("read:", err)
            return
        }
        log.Printf("Received: %s", message)
    }
}
  1. Running the benchmark:
func main() {
    flag.Parse()
    clients := flag.Arg(0)
    log.Printf("Benchmarking %s connections", clients)

    cmd := exec.Command("./client", "-c", clients)
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }
}

Getting Started

To run the WebSocket server:

  1. Clone the repository: git clone https://github.com/eranyanay/1m-go-websockets.git
  2. Navigate to the project directory: cd 1m-go-websockets
  3. Run the server: go run server.go

To run the WebSocket client:

  1. Open a new terminal window
  2. Navigate to the project directory
  3. Run the client: go run client.go

To run the benchmark:

  1. Build the client: go build -o client client.go
  2. Run the benchmark: go run benchmark.go 1000000

Note: Adjust the number of connections as needed for your system's capabilities.

Competitor Comparisons

6,094

Tiny WebSocket library for Go.

Pros of ws

  • More lightweight and focused on low-level WebSocket operations
  • Provides greater flexibility and control over WebSocket connections
  • Offers zero-allocation upgrades and low-level API for custom implementations

Cons of ws

  • Less beginner-friendly due to its low-level nature
  • Requires more manual handling of WebSocket operations
  • May need additional code for higher-level functionality

Code Comparison

1m-go-websockets:

http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
    conn, _ := upgrader.Upgrade(w, r, nil)
    defer conn.Close()
    for {
        _, msg, _ := conn.ReadMessage()
        conn.WriteMessage(websocket.TextMessage, msg)
    }
})

ws:

u := ws.Upgrader{}
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
    conn, _, _, err := u.Upgrade(r, w)
    if err != nil {
        return
    }
    defer conn.Close()
    for {
        msg, op, err := wsutil.ReadClientData(conn)
        if err != nil {
            return
        }
        err = wsutil.WriteServerMessage(conn, op, msg)
        if err != nil {
            return
        }
    }
})

The ws library provides more granular control over the WebSocket connection, allowing for custom handling of operations and messages. 1m-go-websockets offers a simpler, higher-level API for basic WebSocket functionality.

Real-time messaging library for Go. The simplest way to add feature-rich and scalable WebSocket support to your application. The core of Centrifugo server.

Pros of Centrifuge

  • Full-featured real-time messaging framework with support for various protocols (WebSocket, SockJS, HTTP streaming)
  • Built-in scalability features, including Redis engine for horizontal scaling
  • Comprehensive documentation and active community support

Cons of Centrifuge

  • More complex setup and configuration compared to simpler WebSocket implementations
  • Higher resource usage due to additional features and scalability options
  • Steeper learning curve for developers new to real-time messaging systems

Code Comparison

1m-go-websockets:

func wsHandler(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
        return
    }
    // Handle WebSocket connection
}

Centrifuge:

node, _ := centrifuge.New(centrifuge.Config{})
node.OnConnect(func(client *centrifuge.Client) {
    // Handle client connection
})
node.OnSubscribe(func(client *centrifuge.Client, e centrifuge.SubscribeEvent) {
    // Handle subscription
})

The 1m-go-websockets project focuses on raw WebSocket handling, while Centrifuge provides a higher-level abstraction with built-in features for real-time messaging and scalability.

Turn any program that uses STDIN/STDOUT into a WebSocket server. Like inetd, but for WebSockets.

Pros of websocketd

  • Language-agnostic: Works with any programming language or shell script
  • Simple setup: Turns any command-line program into a WebSocket server
  • Flexible: Supports both input and output streams

Cons of websocketd

  • Limited scalability: Not designed for handling millions of concurrent connections
  • Less control: Doesn't provide fine-grained control over WebSocket implementation
  • General-purpose: Not optimized specifically for high-performance WebSocket scenarios

Code Comparison

websocketd:

websocketd --port=8080 ./my_program.py

1m-go-websockets:

http.HandleFunc("/ws", wsHandler)
http.ListenAndServe(":8080", nil)

Summary

websocketd is a versatile tool that allows quick WebSocket server setup for various languages and scripts. It's ideal for prototyping and small-scale applications. 1m-go-websockets, on the other hand, is a Go-specific implementation focused on high performance and scalability, capable of handling a million concurrent WebSocket connections.

websocketd offers simplicity and flexibility across languages, while 1m-go-websockets provides optimized performance for Go applications requiring massive scalability. The choice between them depends on the specific project requirements, language preferences, and scalability needs.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Going Infinite, handling 1M websockets connections in Go

This repository holds the complete implementation of the examples seen in Gophercon Israel talk, 2019.

Going Infinite, handling 1 millions websockets connections in Go / Eran Yanay — [ Video | Slides ]

It doesnt intend or claim to serve as a better, more optimal implementation than other libraries that implements the websocket protocol, it simply shows a set of tools, all combined together to demonstrate a server written in pure Go that is able to serve more than a million websockets connections with less than 1GB of ram.

Usage

This repository demonstrates how a very high number of websockets connections can be maintained efficiently in Linux

Everything is written in pure Go

Each folder shows an example of a server implementation that overcomes various issues raised by the OS, by the hardware or the Go runtime itself, as shown during the talk.

setup.sh is a wrapper to running multiple instances using Docker. See content of the script for more details of how to use it.

destroy.sh is a wrapper to stop all running clients.

A single client instance can be executed by running go run client.go -conn=<# connections to establish>

Remarks

This repo consists of a set of examples that were demonstrated during a live talk in Gophercon.

What you see is what you get - while the implementation is fully functional, it doesn't intend to serve as a production-ready code, and no new features that were asked will be added.

The only purpose of this repository is to serve as a reference and a case study.