go http.Request.Conn.ActiveConn - это карта, поэтому возникнет ли у нее проблема с одновременной картой? - PullRequest
0 голосов
/ 25 июня 2019

go http.Request.Context.ActiveConn - это карта, будет ли у нее проблема с одновременной картой?

Если будет много подключений, я распечатаю request.Context, который включает ActiveConn(map), будет ли онвозникли проблемы с чтением и записью карты?

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "r.ctx: %#v, %+v", r.Context(), r.Context())
    })
    http.ListenAndServe(":1234", nil)
}

Я использую webench для тестирования давления, он не будет выполнен из-за одновременной проблемы с картой.Так есть ли у кого такая же проблема?Из-за этого я испортил основной сервис ... ...

1 Ответ

1 голос
/ 25 июня 2019

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

То, что здесь происходит, заключается в том, что при печати всего r.Context() вы получаете доступ к внутреннему полю объекта Go * Server без синхронизации доступа к нему.

Это вызывает ошибку concurrent map read and map write, которую вы в итоге видите.

Самое простое решение было бы заменить это:

fmt.Fprintf(w, "r.ctx: %#v, %+v", r.Context(), r.Context())

С помощью некоторой пользовательской функции, которую вы пишете, она получает этот объект Context и извлекает значения, которые вам подходят (например, любой пользовательский ключ / значение, которое вы добавили в контекст).

Более подробное объяснение этого поля activeConn

activeConn, который вы видите, когда печатаете весь r.Context(), как это происходит, происходит от типа Server Го.

При подготовке к прослушиванию соединений Server создает базовый контекст, в который он добавляет ссылку на сам Server:

https://github.com/golang/go/blob/master/src/net/http/server.go#L2894

func (srv *Server) Serve(l net.Listener) error {
    ....
    ctx := context.WithValue(baseCtx, ServerContextKey, srv)
    ....
}

Таким образом, при печати всего контекста, вы в конечном итоге печатаете это поле activeConn:

https://github.com/golang/go/blob/master/src/net/http/server.go#L2582

activeConn map[*conn]struct{}

Реализация Server синхронизирует доступ к этой карте, когда она должна использоваться, например, здесь:

https://github.com/golang/go/blob/master/src/net/http/server.go#L2997

...

s.mu.Lock()
defer s.mu.Unlock()
if s.activeConn == nil {
    s.activeConn = make(map[*conn]struct{})
}

if add {
    s.activeConn[c] = struct{}{}
} else {
    delete(s.activeConn, c)
}
....
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...