refactor:简化main函数中pprof的关闭调用

This commit is contained in:
tangerineyu
2026-03-26 12:17:05 +08:00
parent 9a0ba45a51
commit 145bf3fa86
4 changed files with 51 additions and 28 deletions

View File

@@ -66,7 +66,7 @@ func main() {
log.Printf("RabbitMQ connected") log.Printf("RabbitMQ connected")
} }
// Pprof // Pprof
pprofServer, err := observability.StartPprofServer( pprofServer, err := observability.NewPprofServer(
"API", "API",
cfg.ObservabilityConfig.Pprof.Enabled, cfg.ObservabilityConfig.Pprof.Enabled,
cfg.ObservabilityConfig.Pprof.ApiAddr, cfg.ObservabilityConfig.Pprof.ApiAddr,
@@ -74,13 +74,7 @@ func main() {
if err != nil { if err != nil {
log.Printf("Failed to start API pprof server: %v", err) log.Printf("Failed to start API pprof server: %v", err)
} }
defer func() { defer pprofServer.Close()
shutdownCtx, cancel := context.WithTimeout(context.Background(), 3 * time.Second)
defer cancel()
if err := observability.Shutdown(shutdownCtx, pprofServer); err != nil {
log.Printf("Failed to shutdown API pprof server: %v", err)
}
}()
// 设置路由 // 设置路由
r := apphttp.SetRouter(sqlDB, cache, rmq) r := apphttp.SetRouter(sqlDB, cache, rmq)

View File

@@ -122,7 +122,7 @@ func main() {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop() defer stop()
pprofServer, err := observability.StartPprofServer( pprofServer, err := observability.NewPprofServer(
"Worker", "Worker",
cfg.ObservabilityConfig.Pprof.Enabled, cfg.ObservabilityConfig.Pprof.Enabled,
cfg.ObservabilityConfig.Pprof.WorkerAddr, cfg.ObservabilityConfig.Pprof.WorkerAddr,
@@ -130,13 +130,7 @@ func main() {
if err != nil { if err != nil {
log.Printf("Failed to start worker pprof server: %v", err) log.Printf("Failed to start worker pprof server: %v", err)
} }
defer func() { defer pprofServer.Close()
shutdownCtx, cancel := context.WithTimeout(context.Background(), 3 * time.Second)
defer cancel()
if err := observability.Shutdown(shutdownCtx, pprofServer); err != nil {
log.Printf("Failed to shutdown worker pprof server: %v", err)
}
}()
errCh := make(chan error, 4) errCh := make(chan error, 4)
log.Printf("Worker started, consuming queue=%s", socialQueue) log.Printf("Worker started, consuming queue=%s", socialQueue)

View File

@@ -1,6 +1,7 @@
package observability package observability
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"log" "log"
@@ -8,8 +9,14 @@ import (
"net/http" "net/http"
"net/http/pprof" "net/http/pprof"
"time" "time"
"context"
) )
type PprofServer struct {
name string
server *http.Server
shutdownTimeout time.Duration
}
func NewPprofMux() *http.ServeMux { func NewPprofMux() *http.ServeMux {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc("/debug/pprof/", pprof.Index) mux.HandleFunc("/debug/pprof/", pprof.Index)
@@ -21,26 +28,30 @@ func NewPprofMux() *http.ServeMux {
return mux return mux
} }
func StartPprofServer(name string, enabled bool, addr string) (*http.Server, error) { func NewPprofServer(name string, enabled bool, addr string) (*PprofServer, error) {
pprofServer := &PprofServer{
name: name,
shutdownTimeout: 3 * time.Second,
}
if !enabled || addr == "" { if !enabled || addr == "" {
return nil, nil return pprofServer, nil
} }
ln, err := net.Listen("tcp", addr) ln, err := net.Listen("tcp", addr)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to start %s pprof server on %s: %w", name, addr, err) return nil, fmt.Errorf("failed to start %s pprof server on %s: %w", name, addr, err)
} }
server := &http.Server{ pprofServer.server = &http.Server{
Addr: addr, Addr: addr,
Handler: NewPprofMux(), Handler: NewPprofMux(),
ReadHeaderTimeout: 5 * time.Second, ReadHeaderTimeout: 5 * time.Second,
} }
go func() { go func() {
log.Printf("%s pprof listening on %s", name, addr) log.Printf("%s pprof listening on %s", name, addr)
if err := server.Serve(ln); err != nil && !errors.Is(err, http.ErrServerClosed) { if err := pprofServer.server.Serve(ln); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Printf("%s pprof server error: %v", name, err) log.Printf("%s pprof server error: %v", name, err)
} }
}() }()
return server, nil return pprofServer, nil
} }
func Shutdown(ctx context.Context, srv *http.Server) error{ func Shutdown(ctx context.Context, srv *http.Server) error{
@@ -48,4 +59,17 @@ func Shutdown(ctx context.Context, srv *http.Server) error{
return nil return nil
} }
return srv.Shutdown(ctx) return srv.Shutdown(ctx)
}
func (s *PprofServer) Close() error {
if s == nil {
return nil
}
shutdownCtx, cancel := context.WithTimeout(context.Background(), 3 * time.Second)
defer cancel()
if err := Shutdown(shutdownCtx, s.server); err != nil {
log.Printf("Failed to shutdown %s pprof server: %v", s.name, err)
return err
}
return nil
} }

View File

@@ -17,15 +17,26 @@ func TestNewPprofMux(t *testing.T) {
t.Errorf("Expected status code 200, got %d", rr.Code) t.Errorf("Expected status code 200, got %d", rr.Code)
} }
} }
func TestNewPprofServerWithDisabled(t *testing.T) {
func TestStartPprofServerWithDisabled(t *testing.T) {
t.Parallel() t.Parallel()
server, err := StartPprofServer("api", false, "localhost:6060") pprofServer, err := NewPprofServer("api", false, "localhost:6060")
if err != nil { if err != nil {
t.Fatalf("Failed to start pprof server: %v", err) t.Fatalf("Failed to create pprof server: %v", err)
} }
if server != nil { if pprofServer != nil {
t.Fatalf("Expected nil server when pprof is disabled, got non-nil") t.Fatalf("Expected nil pprof server when disabled, got non-nil")
} }
} }
func TestPprofServerCloseWithDisabledServer(t *testing.T) {
t.Parallel()
pprofServer, err := NewPprofServer("api", false, "localhost:6060")
if err != nil {
t.Fatalf("Failed to create pprof server: %v", err)
}
if err := pprofServer.Close(); err != nil {
t.Fatalf("Expected no error when closing disabled pprof server, got: %v", err)
}
}