你正在使用哪个版本的Go(go version
)?
$ go version
go version go1.19.13 linux/amd64
这个问题在最新版本中是否会重现?
是的
你正在使用什么操作系统和处理器架构(go env
)?
go env
输出
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/root/go/pkg/mod"
GOOS="linux"
GOPATH="/root/go"
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.19.13"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2198329798=/tmp/go-build -gno-record-gcc-switches"
你做了什么?
我从http2.transport下载了9M个文件,使用了100个goroutine。
你期望看到什么?
目前http2中有超过100个活动流。我认为连接应该是新打开的,但它没有。
你看到了什么?
检查http2.transport连接池后,我们正在重用一个单一的连接。netstat -nap检查显示有1个连接,接收器已满,发送器已满很多。以下修改通过以20个活动流为单位创建连接来提高性能。
func (cc *ClientConn) State() ClientConnState {
cc.wmu.Lock()
maxConcurrent := cc.maxConcurrentStreams
if !cc.seenSettings {
maxConcurrent = 0
}
cc.wmu.Unlock()
+ // cc.mu.Lock()
+ // defer cc.mu.Unlock()
return ClientConnState{
Closed: cc.closed,
Closing: cc.closing || cc.singleUse || cc.doNotReuse || cc.goAway != nil,
StreamsActive: len(cc.streams),
StreamsReserved: cc.streamsReserved,
StreamsPending: cc.pendingRequests,
LastIdle: cc.lastIdle,
MaxConcurrentStreams: maxConcurrent,
}
}
func (cc *ClientConn) idleStateLocked() (st clientConnIdleState) {
if cc.singleUse && cc.nextStreamID > 1 {
return
}
var maxConcurrentOkay bool
if cc.t.StrictMaxConcurrentStreams {
// We'll tell the caller we can take a new request to
// prevent the caller from dialing a new TCP
// connection, but then we'll block later before
// writing it.
maxConcurrentOkay = true
} else {
maxConcurrentOkay = int64(len(cc.streams)+cc.streamsReserved+1) <= int64(cc.maxConcurrentStreams)
}
st.canTakeNewRequest = cc.goAway == nil && !cc.closed && !cc.closing && maxConcurrentOkay &&
!cc.doNotReuse &&
int64(cc.nextStreamID)+2*int64(cc.pendingRequests) < math.MaxInt32 &&
!cc.tooIdleLocked()
+ if st.canTakeNewRequest {
+ if cc.State().StreamsActive > 20 {
+ st.canTakeNewRequest = false
+ }
+ }
return
}
随着活动流数量的增加,http2变得越来越慢。
7条答案
按热度按时间icnyk63a1#
感谢您的报告。请问您能否通过Playground链接发布您正在使用的代码?
8ehkhllq2#
@neild@tombergan per owners
qlvxas9a3#
测试代码在这里。
https://go.dev/play/p/et4HPzU3wLq?v=goprev
我在我的机器上检查了1个连接。
总响应时间为10秒。
在http1.1中,响应时间在2秒以内。
http2
http1.1
mwkjh3gx4#
请让我知道如果你需要任何更多的信息。
cbeh67ev5#
请注意,服务器可以设置MaxConcurrentStreams,通过#47840也可以实现类似的性能改进。
vm0i2vca6#
我认为我们需要在客户端上设置MaxConcurrentStreams。(http2.transport)
除了go服务器之外,我还使用了诸如go反向代理、nginx等服务器。如果Golang成为客户端,情况也是一样的。
MaxReadFrameSize会波动,但数值保持不变。
9nvpjoqh7#
我正在寻找一些新的东西并与你分享。
我的当前电脑是56核CPU。
你已经设置了runtime.GOMAXPROCS(3)。
http2从10秒变为4秒。
http1从1秒变为4秒。