Почему этот обработчик SSE приводит к зависанию клиентского соединения? - PullRequest
0 голосов
/ 07 февраля 2020

В этом примере, https://github.com/kljensen/golang-html5-sse-example/blob/d4eba81ddea2b4191f039adb6929086ca6b39c0f/server.go#L130, вы можете заблокировать канал. Но выполнение этого в моем HandleExecute приводит к тому, что состояние подключения браузера / клиента остается в состоянии ожидания, и клиенту ничего не отправляется.

Если я удаляю for для l oop и использую команду select оператор с регистром по умолчанию не записывает никаких данных, затем он работает (execute записывает и сбрасывает данные), за исключением того, что обработчик возвращается и клиент повторно соединяется каждые 5 секунд вместо поддержания соединения. Когда я делаю это таким образом, клиент получает потоковые данные только через интервалы переподключения.

Таким образом, в конечном итоге пользователи видят задержку, длящуюся менее 5 секунд, в зависимости от того, когда ударил HandleExecuteRequest. HandleExecute может быть готов к записи, но клиент, возможно, еще не подключился. Я надеюсь, что это имеет смысл.

Как мне написать эти обработчики, чтобы поддерживать постоянное соединение вместо повторного соединения?

func (s *Server) HandleExecuteRequest(w http.ResponseWriter, r *http.Request) {
    err := r.ParseForm()
    if err != nil {
        log.Printf("Error parsing request: %v", err)
        fmt.Fprintf(w, "Error parsing request: %v", err)
        return
    }

    decoder := schema.NewDecoder()
    var f Form
    err = decoder.Decode(&f, r.PostForm)
    if err != nil {
        log.Printf("Error decoding form: %v", err)
        fmt.Fprintf(w, "Error decoding form: %v", err)
        return
    }

    s.clientMap[r.RemoteAddr] <- buildCommand(&f)
}

func (s *Server) HandleExecute(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    s.addClient(r)

    for {
        cmd := <-s.clientMap[r.RemoteAddr]
        execute(w, cmd)
    }
}

Javascript

var source = new EventSource('<host>/execute');
source.onmessage = function(e) {
document.querySelector("code").innerHTML +="<span class='font-weight-bold' style='white-space: pre-wrap; padding-left: 200px;'>" + e.data + "</span>" + "<br>"
};

Если я обновить HandleExecute до ниже, я получаю непрерывное соединение, но затем HandleExecuteRequest застревает в ожидании, когда это ударил. Может, как я настраиваю клиентов и обрабатываю каналы в этом случае.

func (s *Server) HandleExecute(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    s.addClient(r)

    for {
        select {
        case cmd := <-s.clientMap[r.RemoteAddr]:
            execute(w, cmd)
        default:
            fmt.Fprint(w, ": no data\n\n")
        }
    }
}

1 Ответ

0 голосов
/ 07 февраля 2020

Моя проблема не имела отношения к настройке обработчика SSE. Мой канал не был настроен правильно и блокировал соединения.

...