Как в golang сервере отправлять данные на клиент динамически?

Каким образом можно автоматически обновлять данные на сервере и отправлять их на клиент без использования крона и шедулера? Сейчас рассматривается вариант с использованием rabbit + webhook, но он кажется неудобным. Есть ли другие альтернативные подходы для решения этой задачи?
  • 1 февраля 2024 г. 8:28
Ответы на вопрос 2
В Go есть различные подходы для динамической отправки данных на клиент. Один из наиболее популярных способов — использовать WebSockets, которые позволяют устанавливать двусторонний канал связи между клиентом и сервером. Другие варианты включают Server-Sent Events (SSE) и длинные HTTP-опросы (Long-Polling).

Пример реализации с использованием WebSockets в Go с помощью библиотеки `gorilla/websocket`:

1. Установка библиотеки для работы с WebSockets:

```shell
go get github.com/gorilla/websocket
```

2. Пример серверного кода для установки WebSocket соединения:

```go
package main

import (
    "log"
    "net/http"
    "time"
    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        return true // Разрешить соединение с любого источника
    },
}

func main() {
    http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
        conn, err := upgrader.Upgrade(w, r, nil)
        if err != nil {
            log.Println(err)
            return
        }
        defer conn.Close()

        // Цикл отправки сообщений клиенту
        for {
            // Проверка на наличие новых данных для отправки может быть здесь
            time.Sleep(1 * time.Second)
            // Отправка данных клиенту
            if err := conn.WriteJSON(map[string]interface{}{"time": time.Now().String()}); err != nil {
                log.Println(err)
                break
            }
        }
    })

    log.Fatal(http.ListenAndServe(":8080", nil))
}
```

3. Пример клиентского кода на JavaScript для работы с WebSocket:

```javascript
var conn = new WebSocket('ws://localhost:8080/ws');
conn.onopen = function(e) {
    console.log("Соединение установлено!");
};

conn.onmessage = function(e) {
    console.log(e.data); // Отобразить полученные данные от сервера
};
```

Для автоматического обновления данных на сервере, без использования крона и шедулера, можно запустить горутину, которая будет регулярно (в цикле) проверять наличие новых данных (например, в базе данных или через другой сервис) и отправлять их клиентам через открытое WebSocket соединение.

Вместо RabbitMQ и webhook, которые более подходят для асинхронной обработки задач и отправки уведомлений на внешние системы, WebSockets более эффективны и удобны для реализации непрерывного потока данных между клиентом и сервером в реальном времени.
Способов много. Можно использовать или SSE, или http2, или long Polling, или short Polling или Websockets. Причём последний вариант самый предпочтительный почти всегда, так как является очень популярным и шустрым. Замеры я не проводил, но на бумаге протокол Websockets имеет наименьший оверхед из всех способов. Реализаций Websocket очень много для Go. 

Если проект маленький, берите Gorilla-websocket, или fiber-websocket или fasthttp-websocket (зависит от того, какую библиотеку вы используете). Эти технологии очень простые и удовлетворяют почти всем требованиям. В крупных проектах я бы предложил использовать или centrifuge, или centrifugo. centrifuge - это хорошо оптимизированная библиотека, а centrifugo - готовое решение. Они посложнее, но уже оптимизированы и предоставляют fallbacks, если клиент не способен установить websocket.

Если у вас есть специфичные требования, вам следует указать это, потому что сейчас приходится "тыкать в небо".
Похожие вопросы