Files
zhuangang/topics/devops/docker/examples/go-api-compose/main.go
T

55 lines
1.4 KiB
Go

// 一个最小的 Go HTTP 服务,用来演示多阶段构建、健康检查和优雅退出。
package main
import (
"context"
"errors"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func newMux() *http.ServeMux {
mux := http.NewServeMux()
mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok"))
})
mux.HandleFunc("GET /api/hello", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"message":"hello from container"}`))
})
return mux
}
func main() {
addr := ":" + getenv("PORT", "8080")
srv := &http.Server{Addr: addr, Handler: newMux(), ReadHeaderTimeout: 5 * time.Second}
// 容器停止时 Docker 先发 SIGTERM,等待一段时间(默认 10 秒)后才 SIGKILL
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
go func() {
log.Printf("listening on %s", addr)
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}()
<-ctx.Done()
shutdownCtx, cancel := context.WithTimeout(context.Background(), 8*time.Second)
defer cancel()
if err := srv.Shutdown(shutdownCtx); err != nil { // 不再接新请求,等正在处理的请求完成
log.Printf("shutdown: %v", err)
}
log.Println("bye")
}
func getenv(k, def string) string {
if v := os.Getenv(k); v != "" {
return v
}
return def
}