Goroutines с ListenAndServe повышает производительность?



Я не очень хорошо знаком с подпрограммами Go, но так как я работаю с маршрутизатором net/http, я несколько раз видел, чтоListenAndServe() обернут подпрограммой go.



Сервер должен быть способен обрабатывать несколько запросов одновременно из коробки, чтобы быть эффективным. Так зачем идти процедуры, как легкие нити используются?
Обеспечивает ли параллелизм какие-либо преимущества?



Вот пример OpenShift



package main

import (
"fmt"
"net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello OpenShift!")
}

func main() {
http.HandleFunc("/", helloHandler)

go func() {
fmt.Println("serving on 8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
}()

go func() {
fmt.Println("serving on 8888")
err := http.ListenAndServe(":8888", nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
}()
select {}
}
655   3  

3 ответов:

http.ListenAndServe это блокирующий вызов. Если вы хотите выполнить еще одну работу (например, сделать второй вызов http.ListenAndServe), вам нужно переместить его в отдельную функцию goroutine. Это все, что они здесь делают.

Они используют select{} в конце, чтобы заблокировать главную goroutine, так как все их вызовы http.ListenAndServe находятся на других goroutines. Если они не вызовут select{}, программа завершится, потому что main() вернется.

Они могли бы достичь того же самого, отбросив select{} и удалив go func() обертка вокруг последнего блока кода. Но я подозреваю, что они сделали это таким образом, чтобы весь код был согласован.

Но это не имеет никакого отношения к производительности.

В комментариях вы приводили и другие подобные примеры. В первом примере :

func main() {
    http.HandleFunc("/", responsehandler.Handler)
    go func() {
      http.ListenAndServe(":8888", nil)
    }()
    fileservice.NewWatcher()
}

Это вызывает http.ListenAndServe , а затем вызывает fileservice.NewWatcher() (который блокирует). Если бы они не завернули звонок в горотин, fileservice.NewWatcher() никогда бы не позвонили.

Другой два примеры - это обычный кусок шаблонной таблицы:

func init() {
    go func() {
        log.Println(http.ListenAndServe("localhost:6060", nil))
    }()
}

Это включает веб-сервер debug profiler. Опять же, это goroutine, так что вызов init возвращает немедленно, а не блокирует. Этот частный случай позволяет вызывающему объекту просто import _ "profiling" и "волшебным образом" получить веб-сервер debug profiler.

Нет, у него нет никаких особых преимуществ, кроме того, что он"работает в фоновом режиме".

Я не думаю, что вам нужна процедура go, чтобы начать ListenAndServe. Согласно документам го.

"ListenAndServe calls Serve". Подача-это рутина.

ListenAndServe прослушивает сетевой адрес TCP addr, а затем вызывает службу с обработчиком для обработки запросов на входящие соединения. Принятые соединения настраиваются так, чтобы включить сохранение TCP. Обработчик обычно равен нулю, и в этом случае DefaultServeMux использованный. https://golang.org/pkg/net/http/#ListenAndServe

Func Serve (L net.Слушатель, обработчик обработчик) ошибка Serve принимает входящие HTTP-соединения на прослушивателе l, создавая новый сервис goroutine для каждого. Служба goroutines считывает запросы, а затем вызывает обработчик, чтобы ответить на них. Обработчик обычно равен нулю, и в этом случае используется DefaultServeMux. https://golang.org/pkg/net/http/#Serve

Comments

    Ничего не найдено.