Goroutine уже запущен в веб-сервере Go по запросу, но клиент отключается, возможно ли, чтобы веб-сервер закрыл эту конкретную программу? - PullRequest
0 голосов
/ 25 июня 2018

Всякий раз, когда веб-запрос приходит от клиента, он порождает программу для обработки каждого из них.Если клиент случайно отключился от соединения, возможно ли, чтобы веб-сервер закрыл эту конкретную программу или эта программа обнаружит, что клиент уже отключился после того, как выполнил весь свой код?

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

Кроме выхода при возврате из вызываемого обработчика при ошибке чтения или записи - выполняющаяся подпрограмма go не будет автоматически обрабатывать очистку более длительных операций, но Go предоставляет хорошие способы справиться с этим.

Во-первых, если вы не знакомы с контекстным пакетом - это мощный и идиоматический способ синхронизации подпрограмм go с поведением отмены, я настоятельно рекомендую прочитать блог Concurrency GoШаблоны: Контекст .

Что-то вроде следующего:

func MyServiceFunc(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            break
        default:
            //do work
        }
    }
}

func MyRequestHandler(res http.ResponseWriter, req *http.Request) {
    MyServiceFunc(req.Context())       
   //write response...
}

Или вы можете использовать интерфейс CloseNotifier , который также реализует http.ResponseWriter , вы могли бысделать что-то вроде следующего простого примера:

func MyServiceFunc(notifier <-chan bool) {
    for {
        select {
        case <-notifier:
            break
        default:
            //do work
        }
    }
}


func MyRequestHandler(res http.ResponseWriter, req *http.Request) {
    notifier := res.(http.CloseNotifier).CloseNotify()
    MyServiceFunc(notifier)
    //write response...
}

Или и простой пример, использующий объединение обоих подходов:

func MyRequestHandler(res http.ResponseWriter, req *http.Request) {

    notifier := res.(http.CloseNotifier).CloseNotify()
    ctx, cancel := context.WithCancel(req.Context())

    go func(closer <-chan bool) {
        <-closer //the notifer blocks until the send
        cancel() //explicitly cancel all go routines
    }(notifier)

    go MyServiceFunc(ctx)
    MyOtherServiceFunc(ctx)
    //write response...
}
0 голосов
/ 26 июня 2018

Процедура соединения для соединения завершается при возврате из обработчика, если при чтении или записи в соединение возникает ошибка или когда заголовки запроса или ответа указывают, что соединение должно быть закрыто.

Обработчики могут проверить наличиезакрытое соединение с использованием Context , возвращенного из Request.Context () .

...