go x/pkgsite/cmd/frontend:不再在代理模式下加载stdlib

vqlkdk9b  于 5个月前  发布在  Go
关注(0)|答案(9)|浏览(57)

你正在使用的Go版本是什么( go version )?

$ go version
go version go1.20.2 linux/amd64

这个问题在最新版本中是否重现?

是的

你正在使用什么操作系统和处理器架构( go env )?

go env 输出

$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/net_home/alatter/.cache/go-build"
GOENV="/net_home/alatter/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/net_home/alatter/go/pkg/mod"
GONOPROXY="*."
GONOSUMDB="*."
GOOS="linux"
GOPATH="/net_home/alatter/go"
GOPRIVATE="*.epic.com"
GOPROXY=",direct"
GOROOT="/net_home/alatter/local/go1.20.2.linux-amd64"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/net_home/alatter/local/go1.20.2.linux-amd64/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.20.2"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/net_home/alatter/source/pkgsite/go.mod"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1051915940=/tmp/go-build -gno-record-gcc-switches"

你做了什么?

我们运行pkgsite并将其内部托管,以便为我们自己的包提供文档。我们在“直接”模式下运行它,并通过我们的内部go-proxy(Athena)发送,该代理具有获取我们内部go-modules的凭据。
我们使用以下参数运行pkgsite:

$ go run ./cmd/frontend -bypass_license_check -direct_proxy -proxy_url https://<redacted> -host :8080

在提交f159e616582641bdbeb2d6a0018ca4c8c472fbb5之后,我们无法再加载godocs
对于stdlib包 - 例如,加载http://localhost:8080/io将返回HTTP-500,其中包含来自pkgsite的以下日志:

2023/09/26 15:11:41 Info: Listening on addr :8080
2023/09/26 15:11:46 Info: 0 /io map[requestType:request start]
2023/09/26 15:11:46 Info: FetchDataSource: fetching std@latest
2023/09/26 15:11:46 Info: FetchDataSource: fetched std@latest using *fetch.proxyModuleGetter in 226.3µs with error FetchModule("std", "latest"): proxy.Client.Info("std", "latest"): Client.readBody("std", "latest", "info"): Client.escapedURL("std", "latest", "info"): path: malformed module path "std": missing dot in first path element: invalid argument
2023/09/26 15:11:46 Error: serveUnitPage(ctx, w, r, ds, &{io std latest}): FetchDataSource.GetUnitMeta("io", "std", "latest"): FetchDataSource.findModule("io", "std", "latest"): FetchDataSource.getModule("std", "latest"): FetchModule("std", "latest"): proxy.Client.Info("std", "latest"): Client.readBody("std", "latest", "info"): Client.escapedURL("std", "latest", "info"): path: malformed module path "std": missing dot in first path element: invalid argument
2023/09/26 15:11:46 Info: 500 /io map[isRobot:false requestType:request end]

错误malformed module path "std": missing dot in first path element: invalid argument似乎来自我们的go-proxy(Athena)。它被拒绝一个名为std的模块,这似乎是合理的拒绝。
(编辑:进一步测试后发现错误是pkgsite内部的 - 直接代理模式下的加载stdlib模块似乎与该模式不兼容)
如果我在前端启动的direct-mode分支的fetchdatasource.Options中交换使用的getter顺序,对我来说一切都可以正常工作:

if *directProxy {
		sourceClient := source.NewClient(&http.Client{Transport: &ochttp.Transport{}, Timeout: 1 * time.Minute})
		ds := fetchdatasource.Options{
			Getters: []fetch.ModuleGetter{
				fetch.NewProxyModuleGetter(proxyClient, sourceClient), // <-- if I move this down one line my problem goes away
				fetch.NewStdlibZipModuleGetter(),
			},
			ProxyClientForLatest: proxyClient,
			BypassLicenseCheck:   *bypassLicenseCheck,
		}.New()
		dsg = func(context.Context) internal.DataSource { return ds }
	} else {

二分查找结果:

f159e616582641bdbeb2d6a0018ca4c8c472fbb5 is the first bad commit
commit f159e616582641bdbeb2d6a0018ca4c8c472fbb5
Author: Michael Matloob <matloob@golang.org>
Date:   Wed Jul 5 14:02:46 2023 -0400

    internal/fetch: add two stdlib getters

    This breaks out the behavior of getting the stdlib into its own
    getter, stdlibZipModuleGetter. Most (but not all) of the special cases
    in the fetch code for the stdlib are in the stdlibZipModuleGetter,
    which is installed on the frontend. For the local pkgsite command, we
    add a new builder for the goPackagesModuleGetter that loads the
    packages from the stdlib given a GOROOT. The stdlibZipModuleGetter is
    also installed for pkgsite in as a fallback if the
    goPackagesModuleGetter doesn't successfully fetch the stdlib module
    (I'm not sure if that's possible).

    Fixes #60114

    Change-Id: Ida6a5367343643cc337c6d05e0d40095f79ca9e5
    Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/507883
    Reviewed-by: Jamal Carvalho <jamal@golang.org>
    TryBot-Result: Gopher Robot <gobot@golang.org>
    Run-TryBot: Michael Matloob <matloob@golang.org>
    kokoro-CI: kokoro <noreply+kokoro@google.com>
b5buobof

b5buobof1#

如果我在前端启动的直接模式分支中交换fetchdatasource.Options中使用的getters的顺序,似乎对我来说一切都正常:
嗯。我怀疑这是fetch.proxyModuleGetter的一个bug。./internal/fetchdatasource检查derrors.NotFound以跳过错误:
https://cs.opensource.google/go/x/pkgsite/+/master:internal/fetchdatasource/fetchdatasource.go;l=166-168;drc=14233af499055be3ba3fe6816af8e7d4a4efa9ad
可能如果从fetch.proxyModuleGetter请求一个具有无效路径的模块,它应该返回一个错误,其中errors.Is(err, derrors.NotFound)返回true。
@aslatter,想要发送修复吗?

snz8szmq

snz8szmq2#

解:要使$\dfrac{x+3}{2}\le 10$,

$x+3\le 20$,

$x\le 17$.

故答案为$x\le 17$。

lp0sw83n

lp0sw83n3#

这似乎对于转换来说是一个太低的级别。
看起来在 ./internal/fetch 中已经有了针对标准库的特殊情况:
https://cs.opensource.google/go/x/pkgsite/+/master:internal/fetch/fetch.go;l=77-104;drc=14233af499055be3ba3fe6816af8e7d4a4efa9ad
也许 if fr.ModulePath == stdlib.ModulePath 条件应该在 switch mg.(type) 之前移动?

j5fpnvbx

j5fpnvbx4#

我想到了两个选项:

  1. 在代理客户端的方法内部对"std"进行特殊处理,并直接返回"NotFound"(至少在"info"中如此,但将其扩展到其他"getters"是有意义的)。
  2. 在"./internal/fetch"中对"std"进行特殊处理,跳过不合适的模块获取器。
    这两种方法都感觉有点不太好 - (2)具有更高的组件耦合密度,但(1)需要代理客户端了解"std"模块。
    我对问题描述中获取器的顺序进行的评论并不是一个严肃的建议 - 它更多地描述了我为了诊断问题而采取的行动。但它似乎并不比这些选项更糟?每个由stdlib-getter处理的模块都无法由proxy-getter处理。
zmeyuzjn

zmeyuzjn6#

就我所知,这个问题是运行在"直接代理"模式下的障碍。任何解决方法都将不胜感激(或者对于非代理模式的运行提供指导/建议)。
我很乐意发送修复程序,但似乎我们想要采取的方向并不明确。

pbpqsu0x

pbpqsu0x7#

我不确定这是否相关,但即使在数据库模式下,我也无法让前端提供stdlib(只能得到404响应)。据我所知,数据库必须填充stdlib信息,但这只由一个工作器完成,而这个工作器只有在前端托管在GCP上时才会运行?我很难理解这一切是如何运作的。

wz1wpwve

wz1wpwve8#

我预计这是一个不同的问题——在直接代理模式下,如果请求被路由到后端进行处理,那么stdlib浏览几乎可以正常工作。一旦发生这种情况,发现/下载就会在实时进行,类似于代理发现的包/模块。

eivnm1vs

eivnm1vs9#

是的,我想我弄明白了需要运行 seeddb 来用标准库信息填充数据库。不幸的是,当我运行它时,我的PostgreSQL示例由于OOM错误(32GB的RAM)而被终止。所以这与直接代理模式无关,但我不知道为什么前端在使用数据库运行时不直接获取标准库,就像获取任何其他缺失的包一样。

相关问题