【问题标题】:AppEngine deploy cannot find Go packagesAppEngine 部署找不到 Go 包
【发布时间】:2021-01-15 01:46:09
【问题描述】:

我在 monorepo 中有一个 AppEngine 微服务设置,服务之间有共享代码,所以我进行了重构以统一我的 go 模块(它们非常相似)。重构在本地工作,构建并运行,Goland 编译愉快。我的问题是 AppEngine 部署不再有效, 接收错误如:

Error message: cmd/main.go:4:2: cannot find package "github.com/gin-gonic/gin" in any of:
        /usr/local/go/src/github.com/gin-gonic/gin (from $GOROOT)
        /layers/google.go.appengine_gopath/gopath/src/github.com/gin-gonic/gin (from $GOPATH)
cmd/main.go:5:2: cannot find package "mymodulename/customer/internal/mypkg" in any of:
        /usr/local/go/src/mymodulename/customer/internal/cauth (from $GOROOT)
        /layers/google.go.appengine_gopath/gopath/src/mymodulename/customer/internal/mypkg (from $GOPATH)

原始结构

    > svc1
      > cmd/main.go
      > internal
         >utils/shared.go
         >mypkg
      > go.mod
      > app.yaml
    > svc2
      > cmd/main.go
      > internal
         >utils/shared.go
         >mypkg
      > go.mod
      > app.yaml

重构后

    > svc1
      > cmd/main.go
      > internal
         >mypkg
      > app.yaml
    > svc2
      > cmd/main.go
      > internal
         >mypkg
      > app.yaml
    > internal (common shared stuff)
      > utils/shared.go
    go.mod

重点是 utils/shared.go 移到了各个服务目录之外,统一了 go.mod。

我不清楚的是,当我运行glcoud app deploy 时,AppEngine 是否会在我的本地机器上构建 go 二进制文件,或者是否捆绑所有内容并在云构建中运行它。

  1. AppEngine 部署如何工作?
  2. 如何让 AppEngine 部署以找到我的 go.mod 文件?
  3. 如何捆绑依赖项? (如果它在 CloudBuild 上运行,它肯定无权访问私有存储库)

【问题讨论】:

    标签: go google-app-engine google-cloud-platform google-app-engine-golang


    【解决方案1】:

    回答您的问题:

    AppEngine 部署如何工作?

    • 您的源文件已上传到 Google Cloud Storage。 Cloud Build 构建您的应用并将其部署到 App Engine。

    如何让 AppEngine 部署找到我的 go.mod 文件?

    • 您将模块的 go.mod 文件与 app.yaml 文件放在同一目录中。

    依赖是如何捆绑的?

    • 确实在运行 Cloud Build。 App Engine 无法在构建过程中下载您的私有依赖项,因此您必须在部署时将它们包含在您的应用程序代码中。详细信息可在“指定依赖关系”文档页面的Using private dependencies 段落中找到。

    关于重构你的文件结构:文件结构需要遵守Structuring your files段落中给出的规定:

    • go-app/:Go 1.11 服务的目录。
      • app.yaml:您的服务的配置设置。
      • main.go:您的应用程序代码。

    【讨论】:

    • 感谢您阐明构建的工作原理,这对我理解问题所在有很大帮助。我已经扫描了所有文档,但似乎找不到任何有用的信息来在构建中包含外部文件,例如一个可能在服务之间共享的 firebase 配置文件。我猜每个人都只是沿着制作 util repos 和设置云构建的路线进行访问。不幸的是,我正在使用 go114 并且似乎没有太多关于该主题的新文献,我相信自 1.11 以来依赖关系已经发生了很大变化
    • 关于依赖关系,运行在 Go 1.12+ 标准运行时的应用可以使用任何兼容 linux/amd64 的包: import "github.com/example/mypackage" 为 Cloud Build 制作 repos 的路线是不是文档中推荐的,你应该Vendor dependencies
    • 我在最终解决方案中使用了 vendoring,感谢您的建议
    【解决方案2】:

    我为遇到相同问题的其他人提供的解决方案。 一些事实似乎存在,尽管文档对此有些模棱两可。 docs 说:

    Create your module's go.mod file in the same directory as your app.yaml file. App Engine searches the current directory, then successive parent directories until it finds a go.mod file.
    

    但这似乎不是真的,事实上,app.yaml 文件上方似乎根本没有复制任何内容。

    所以解决方案需要:

    1. 每个微服务都有自己的 go.mod 文件。
    2. go.mod 文件与 app.yaml 位于同一目录中
    3. go mod edit 用于告诉 Go 编译器在本地查找,而不是尝试通过 Internet 获取。
    4. Vendoring 用于将所有依赖项捆绑在与 app.yaml 相同的目录中,以便将它们部署到 AppEngine。

    关于本地导入的一些信息

    Go 似乎首先在依赖项缓存/路径中查找所有内容,然后完全在 Internet 上查找。 如果我使用go mod init shared 创建我的本地包,它的模块名称是“共享”。 要告诉 Go 您想在本地导入而不是使用 Internet,请调用 go mod edit -replace=shared=../../shared/, 你应该看到你的 go.mod 得到了类似replace shared => ../../shared 的行。 如果您使用的是 Goland,但仍然无法编译,请尝试 File>Invalidate Caches/Restart...

    关于供应商的一些信息

    您的 go.mod 文件夹中的go mod vendor 将捆绑所有依赖项,包括本地依赖项,以便它们可以由 AppEngine 部署。这也是处理私有存储库的好方法,因此您无需通过 git Cloud Build 访问您的存储库。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-08
      • 2014-01-27
      • 1970-01-01
      • 1970-01-01
      • 2016-06-29
      • 2014-06-11
      • 1970-01-01
      相关资源
      最近更新 更多