Я пытаюсь написать код для потоковой передачи данных по теме, например, радиостанции (один вещатель, несколько слушателей).Я застрял на том, как обработать новый запрос на соединение WebSocket, не имея процедуры для каждого открытого WebSocket (который начинает становиться ресурсоемким для многих "слушателей" одной и той же "станции").
НаНа данный момент у меня есть карта структур dataStream, которая выглядит следующим образом:
struct dataStream {
data chan byte[]
conns []*websocket.Connection
}
И вот псевдокод для обновления запроса до WebSocket, а затем для попытки добавить соединение WebSocket в conns dataStreams:
func process_request(w http.ResponseWriter, r *http.Request) {
// hundred lines of business logic...
c := upgrade websocket connection
defer c.Close()
if dataStream exists {
append the new connection c to the dataStream.conns slice
} else {
create new dataStream
append the new connection c to the dataStream.conns slice
stream(dataStream)
}
}
И вот функция stream
, упомянутая в приведенном выше блоке кода.Один из них выполняется в фоновом режиме для каждого dataStream (не для каждого соединения WebSocket).
func stream(ds *dataStream) {
ticker := time.NewTicker(poll every ~10 seconds)
go func() { // this is to poll and remove closed connections
for _ = range ticker.C {
for traverse ds.conns {
ping all connections, remove any closed ones and free memory
if len(ds.conns == 0){ // no more connections are listening to this dataStream
delete the ds dataStream and free the memory
stop ticker
return // kill goroutine and free the memory
}
}
}}()
while len(ds.conns) != 0 { // while there are open connections
fetch any available <-ds.data from channel
write the data as websocket message to each connection
}
}
Проблема этого подхода заключается в том, что в функции process_request
, как только поток достигает дна if statement
2-го и последующих подключений, после того, как новое подключение добавлено к срезу dataStream.conns
, функция завершает закрытие соединения WebSocket! В результате stream()
работает в фоновом режиме и опрашивает, чтозакрытое соединение было добавлено к срезу ds.conns
и удаляет его.
Отсюда мой вопрос:
Какой подход я должен использовать, чтобы сохранить соединение WebSocket открытым длядаже после того, как функция обработчика process_request
вернется, предпочтительно без запуска отдельной процедуры для каждого соединения?