部署的应用程序立即关闭

huangapple go评论96阅读模式
英文:

Deployed application shuts itself down immediately

问题

我有一个Go的REST API应用程序。我将其Docker化并部署到Kubernetes上。
在我的本地环境中,它按预期工作。

但是在Kubernetes中,应用程序会自行关闭,并重新启动Pod。

它不会打印任何内容、日志或失败信息。

import (
	"github.com/gorilla/mux"
	"net/http"
	"log"
)

func main() {
	controller := controllers.Controllers{}
	router := mux.NewRouter()
	router.HandleFunc("/customer", controller.GetCustomer()).Methods("GET")
	router.HandleFunc("/customer", controller.InsertCustomer()).Methods("POST")
	router.HandleFunc("/healthcheck", controller.HealthCheck())

	addr := ":" + os.Getenv("PORT")
	srv := &http.Server{Addr: addr, Handler: router}

	go func() {
		if err := srv.ListenAndServe(); err != nil {
			log.Fatalf("listenAndServe failed: %v", err)
		}
	}()
	println("reached here")
}

令人惊讶的是,当我查看日志时,它会打印出"reached here"这一行。
我检查了env变量,它也是正确的。
我怀疑调用listenAndServe失败了,但我找不到一个合理的答案。

英文:

I have a Go rest API application. And I Dockerized it and deployed it to Kubernetes.
It is working as it should on my local.

But in Kubernetes, the application shuts down itself, and the pod is restarted.

It doesn't print anything, any log, or any fail.

import ( 
" github.com/gorilla/mux"
"net/http"
"log"

)   
func main() {
  	controller := controllers.Controllers{}
	router := mux.NewRouter()
	router.HandleFunc("/customer", controller.GetCustomer()).Methods("GET")
	router.HandleFunc("/customer", controller.InsertCustomer()).Methods("POST")
	router.HandleFunc("/healthcheck", controller.HealthCheck())

	addr := ":" + os.Getenv("PORT")
	srv := &http.Server{Addr: addr, Handler: router}

	go func() {
		if err := srv.ListenAndServe(); err != nil {
			log.Fatalf("listenAndServe failed: %v", err)
		}
	}()
    println("reached here")
}

Surprisingly it prints the "reached here" line when I look at the logs.
I checked the env variable, and it is also correct.
I suspect that the call to listenAndServe fails, but I couldn't find a reasonable answer for that.

答案1

得分: 4

main()函数结束时,你的应用程序也会结束。它不会等待其他非main的goroutine完成。参见规范:程序执行

程序的执行从初始化主包开始,然后调用函数main。当该函数调用返回时,程序退出。它不会等待其他(非main)的goroutine完成。

由于你在一个新的goroutine中启动了监听器,所以没有什么阻塞main()的东西,没有其他事情可做(在打印"reached here"之后),所以你的应用程序结束了。请注意,内置的println()函数打印到标准错误输出,这就是为什么你可能看不到任何日志(标准输出和标准错误输出可能保存/重定向到不同的位置)。

最简单的“修复”方法是在main()函数中开始监听:

srv := &http.Server{Addr: addr, Handler: router}

if err := srv.ListenAndServe(); err != nil {
    log.Fatalf("listenAndServe failed: %v", err)
}
英文:

When the main() function ends, your app ends as well. It does not wait for other non-main goroutines to finish. See Spec: Program execution:

> Program execution begins by initializing the main package and then invoking the function main. When that function invocation returns, the program exits. It does not wait for other (non-main) goroutines to complete.

Since you start the listerer in a new goroutine, there's nothing "blocking" main(), there's nothing left to do (after printing "reached here"), so your app ends. Note that the builtin println() prints to the standard error, that's why you may not see any logs (standard output and standard error may be saved / redirected to different places).

The easiest "fix" is to start listening in main():

srv := &http.Server{Addr: addr, Handler: router}

if err := srv.ListenAndServe(); err != nil {
    log.Fatalf("listenAndServe failed: %v", err)
}

huangapple
  • 本文由 发表于 2021年9月1日 14:59:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/69009108.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定