【问题标题】:GAE Go "The request failed because the instance could not start successfully"GAE Go“请求失败,因为实例无法成功启动”
【发布时间】:2020-02-16 13:52:33
【问题描述】:

我已经使用 Google App Engine Go 进行了一段时间的开发,但我已经有一年没有接触过它了。我尝试将我的应用程序从“go1”(1.9?)更新为“go111”,但我目前遇到了一些奇怪的错误,但没有任何解释发生了什么。

错误包括:

  • The request failed because the instance could not start successfully
  • Container called exit(1).
  • 500 Internal server error

这些都没有指向我的代码中任何会出错的特定行,也没有解释任何更有意义的东西......

我猜这个错误是由于我在 golang 版本之间升级造成的。我不得不将app 包更改为main,向应用程序添加main 函数,将appengine 包更新到较新版本,更新gsuite 应用程序,添加云编译小部件,更改app.yaml 脚本从 go 到 auto 等。

总而言之,我迷路了。 A Similar SE question yielded no good answersSomeone else suggested app.yaml might be at fault, so here is mine:

runtime:     go111

handlers:
- url: /static
  static_dir: static
- url: /res
  static_dir: res
- url: /update
  script: auto
  secure: always
  login: admin
- url: /.*
  script: auto
  secure: always
  login: optional

调试控制台日志非常无用:

主文件看起来基本上是这样的:

package main

import (
    "fmt"
    "google.golang.org/appengine"
    "html/template"
    "log"
    "net/http"
)

var MainTemplate *template.Template

func main() {
    http.HandleFunc("/", hello)

    var err error
    MainTemplate, err = template.ParseFiles("html/main.html")
    if err != nil {
        log.Printf("ERROR! %v\n", err.Error())
        panic(err)
    }
    log.Printf("Hello world!\n")
}


func hello(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    //................................//
    MainTemplate.Execute(w, nil)
}

还有什么可能吗?

【问题讨论】:

  • 您的代码很可能崩溃了。添加来自 Stackdriver 的错误消息以及您的代码。
  • @JohnHanley 添加了日志,以及基本代码。主函数似乎没有崩溃,没有错误指向任何错误...
  • @ThePiachu 您似乎错过了对 http.ListenAndServe 的调用。看看go111 getting started page 中的 helloworld.go 示例。否则,您的应用将退出而不会监听任何请求(或者,您似乎可以根据 migration guide 调用 appengine.Main)。
  • 您发布的代码以前无法在 App Engine 中运行。您的代码启动、处理模板并退出。未启动任何 Web 服务器进程。
  • @JohnHanley 是的,那个函数曾经是 init(),但后来 appengine 告诉我没有 main 包和 main() 函数,所以我只是将 init 切换到 main。我想我的头脑已经忽略了示例中的 ListenAndServe,因为它嵌套在日志中...github.com/GoogleCloudPlatform/golang-samples/blob/master/…

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


【解决方案1】:

好的,在几个 cmets 的帮助下,我必须解决以下几个问题才能让我的代码正常工作:

  1. 我将init() 函数转换为main(),但没有添加监听请求的方法。代码刚刚通过main()函数并没有错误地退出,因此调试出现问题。
  2. appengine.NewContext(r) 显然已被弃用,因此我不得不将这些语句切换为 r.Context()。同时,Appengine Datastore 仍在使用golang.org/x/net/context 而不仅仅是context,所以如果你想使用RunInTransaction() 之类的东西,不要更新你的导入,context 转换成golang.org/x/net/context 就好了
  3. 如果你follow the official examples 由谷歌提供,你很可能会遇到textPayload: "2019/10/20 22:32:46 http: panic serving 127.0.0.1:16051: not an App Engine context 之类的错误。相反,您的代码需要类似于以下示例。
  4. 由于以前的app 包现在是main 包,请确保app.yaml(例如favicon.ico)中引用的所有文件相对于main 包位于适当的位置(我不得不将我的移动到不同的文件夹以避免每次请求都弹出错误...)。
package main

import (
    "google.golang.org/appengine"
    "html/template"
    "net/http"
)

var MainTemplate *template.Template

func init() {
    http.HandleFunc("/", hello)
    MainTemplate, _= template.ParseFiles("html/main.html")
}

func main() {
    appengine.Main()
}

func hello(w http.ResponseWriter, r *http.Request) {
    c := r.Context()
    //................................//
    MainTemplate.Execute(w, nil)
}

这应该有效。 appengine.Main() 显然将您连接到使用数据存储/内存缓存/任何操作的上下文所需的所有 appengine 功能。

感谢帮助我克服第一次困难的评论者!

【讨论】:

    【解决方案2】:

    您的代码缺少启动侦听器的部分。将此添加到您的代码中:

        port := os.Getenv("PORT")
        if port == "" {
                port = "8080"
                log.Printf("Defaulting to port %s", port)
        }
        log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
    

    【讨论】:

    • 关闭,但这显然不允许您将Context 正确用于datastore 以及您有什么。所以显示一个网页就足够了,但对于一个完整的 appengine 应用程序来说还不够好......
    • @ThePiachu - 您的问题中的数据存储在哪里?
    • 不是的,我用的更深了几层,直到第一层问题修复才知道这是个问题。
    猜你喜欢
    • 2020-03-07
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    • 2017-09-23
    • 1970-01-01
    • 1970-01-01
    • 2020-08-28
    • 2023-03-14
    相关资源
    最近更新 更多