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 {}
}
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