From 11151586165946453275b66ef33794d41a5e047b Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Mon, 27 Jan 2025 08:18:34 -0700 Subject: [PATCH 1/4] caddyhttp: ResponseRecorder sets stream regardless of 1xx Fixes a panic where rr.stream is not true when it should be in the event of 1xx, because the buf is nil --- modules/caddyhttp/responsewriter.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/caddyhttp/responsewriter.go b/modules/caddyhttp/responsewriter.go index 3c0f89d0b33..904c30c0352 100644 --- a/modules/caddyhttp/responsewriter.go +++ b/modules/caddyhttp/responsewriter.go @@ -154,16 +154,16 @@ func (rr *responseRecorder) WriteHeader(statusCode int) { // connections by manually setting headers and writing status 101 rr.statusCode = statusCode + // decide whether we should buffer the response + if rr.shouldBuffer == nil { + rr.stream = true + } else { + rr.stream = !rr.shouldBuffer(rr.statusCode, rr.ResponseWriterWrapper.Header()) + } + // 1xx responses aren't final; just informational if statusCode < 100 || statusCode > 199 { rr.wroteHeader = true - - // decide whether we should buffer the response - if rr.shouldBuffer == nil { - rr.stream = true - } else { - rr.stream = !rr.shouldBuffer(rr.statusCode, rr.ResponseWriterWrapper.Header()) - } } // if informational or not buffered, immediately write header From 066d770409917b409d0bdc14cb5ba33d3e4cb33e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 27 Jan 2025 17:32:24 +0100 Subject: [PATCH 2/4] cmd: automatically set GOMEMLIMIT (#6809) * feat: automatically set GOMEMLIMIT * add system support * comments * add logs --- cmd/main.go | 23 ++++++++++++++++++++++- go.mod | 2 ++ go.sum | 4 ++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/cmd/main.go b/cmd/main.go index 655c0084bea..c41738be045 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -24,6 +24,7 @@ import ( "io" "io/fs" "log" + "log/slog" "net" "os" "path/filepath" @@ -33,10 +34,12 @@ import ( "strings" "time" + "github.com/KimMachineGun/automemlimit/memlimit" "github.com/caddyserver/certmagic" "github.com/spf13/pflag" "go.uber.org/automaxprocs/maxprocs" "go.uber.org/zap" + "go.uber.org/zap/exp/zapslog" "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig" @@ -66,12 +69,30 @@ func Main() { os.Exit(caddy.ExitCodeFailedStartup) } - undo, err := maxprocs.Set() + logger := caddy.Log() + + // Configure the maximum number of CPUs to use to match the Linux container quota (if any) + // See https://pkg.go.dev/runtime#GOMAXPROCS + undo, err := maxprocs.Set(maxprocs.Logger(logger.Sugar().Infof)) defer undo() if err != nil { caddy.Log().Warn("failed to set GOMAXPROCS", zap.Error(err)) } + // Configure the maximum memory to use to match the Linux container quota (if any) or system memory + // See https://pkg.go.dev/runtime/debug#SetMemoryLimit + _, _ = memlimit.SetGoMemLimitWithOpts( + memlimit.WithLogger( + slog.New(zapslog.NewHandler(logger.Core())), + ), + memlimit.WithProvider( + memlimit.ApplyFallback( + memlimit.FromCgroup, + memlimit.FromSystem, + ), + ), + ) + if err := defaultFactory.Build().Execute(); err != nil { var exitError *exitError if errors.As(err, &exitError) { diff --git a/go.mod b/go.mod index 35f06bcd800..4d9f5ff36a1 100644 --- a/go.mod +++ b/go.mod @@ -49,6 +49,7 @@ require ( require ( dario.cat/mergo v1.0.1 // indirect + github.com/KimMachineGun/automemlimit v0.7.0 // indirect github.com/Microsoft/go-winio v0.6.0 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -63,6 +64,7 @@ require ( github.com/google/pprof v0.0.0-20231212022811-ec68065c825e // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect github.com/onsi/ginkgo/v2 v2.13.2 // indirect + github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/quic-go/qpack v0.5.1 // indirect github.com/smallstep/go-attestation v0.4.4-0.20240109183208-413678f90935 // indirect diff --git a/go.sum b/go.sum index b5622ba512e..909c7e0b93a 100644 --- a/go.sum +++ b/go.sum @@ -31,6 +31,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/KimMachineGun/automemlimit v0.7.0 h1:7G06p/dMSf7G8E6oq+f2uOPuVncFyIlDI/pBWK49u88= +github.com/KimMachineGun/automemlimit v0.7.0/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= @@ -366,6 +368,8 @@ github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv/v3 v3.0.1 h1:x06SQA46+PKIUftmEujdwSEpIx8kR+M9eLYsUxeYveU= github.com/peterbourgon/diskv/v3 v3.0.1/go.mod h1:kJ5Ny7vLdARGU3WUuy6uzO6T0nb/2gWcT1JiBvRmb5o= From d7872c3bfa673ce9584d00f01a725b93fa7bedf1 Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Mon, 27 Jan 2025 21:42:09 +0300 Subject: [PATCH 3/4] caddytls: Refactor sni matcher (#6812) --- modules/caddytls/matchers.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/caddytls/matchers.go b/modules/caddytls/matchers.go index fec1ffd8e31..dfbec94cc7a 100644 --- a/modules/caddytls/matchers.go +++ b/modules/caddytls/matchers.go @@ -56,7 +56,7 @@ func (MatchServerName) CaddyModule() caddy.ModuleInfo { // Match matches hello based on SNI. func (m MatchServerName) Match(hello *tls.ClientHelloInfo) bool { - repl := caddy.NewReplacer() + var repl *caddy.Replacer // caddytls.TestServerNameMatcher calls this function without any context if ctx := hello.Context(); ctx != nil { // In some situations the existing context may have no replacer @@ -65,6 +65,10 @@ func (m MatchServerName) Match(hello *tls.ClientHelloInfo) bool { } } + if repl == nil { + repl = caddy.NewReplacer() + } + for _, name := range m { rs := repl.ReplaceAll(name, "") if certmagic.MatchWildcard(hello.ServerName, rs) { From 904a0fa368b7eacac3c7156ce4a1f6ced8f61f34 Mon Sep 17 00:00:00 2001 From: Mohammed Al Sahaf Date: Tue, 28 Jan 2025 00:30:54 +0300 Subject: [PATCH 4/4] reverse_proxy: re-add healthy upstreams metric (#6806) * reverse_proxy: re-add healthy upstreams metric Signed-off-by: Mohammed Al Sahaf * lint Signed-off-by: Mohammed Al Sahaf --------- Signed-off-by: Mohammed Al Sahaf --- modules/caddyhttp/reverseproxy/metrics.go | 20 ++++++++++--------- .../caddyhttp/reverseproxy/reverseproxy.go | 4 ++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/modules/caddyhttp/reverseproxy/metrics.go b/modules/caddyhttp/reverseproxy/metrics.go index f744756d3f9..8a7105c1193 100644 --- a/modules/caddyhttp/reverseproxy/metrics.go +++ b/modules/caddyhttp/reverseproxy/metrics.go @@ -2,26 +2,26 @@ package reverseproxy import ( "runtime/debug" - "sync" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "go.uber.org/zap" "go.uber.org/zap/zapcore" + + "github.com/caddyserver/caddy/v2" ) var reverseProxyMetrics = struct { - init sync.Once upstreamsHealthy *prometheus.GaugeVec logger *zap.Logger }{} -func initReverseProxyMetrics(handler *Handler) { +func initReverseProxyMetrics(handler *Handler, registry *prometheus.Registry) { const ns, sub = "caddy", "reverse_proxy" upstreamsLabels := []string{"upstream"} - reverseProxyMetrics.upstreamsHealthy = promauto.NewGaugeVec(prometheus.GaugeOpts{ + reverseProxyMetrics.upstreamsHealthy = promauto.With(registry).NewGaugeVec(prometheus.GaugeOpts{ Namespace: ns, Subsystem: sub, Name: "upstreams_healthy", @@ -35,17 +35,19 @@ type metricsUpstreamsHealthyUpdater struct { handler *Handler } -func newMetricsUpstreamsHealthyUpdater(handler *Handler) *metricsUpstreamsHealthyUpdater { - reverseProxyMetrics.init.Do(func() { - initReverseProxyMetrics(handler) - }) +const upstreamsHealthyMetrics caddy.CtxKey = "reverse_proxy_upstreams_healthy" +func newMetricsUpstreamsHealthyUpdater(handler *Handler, ctx caddy.Context) *metricsUpstreamsHealthyUpdater { + if set := ctx.Value(upstreamsHealthyMetrics); set == nil { + initReverseProxyMetrics(handler, ctx.GetMetricsRegistry()) + ctx = ctx.WithValue(upstreamsHealthyMetrics, true) + } reverseProxyMetrics.upstreamsHealthy.Reset() return &metricsUpstreamsHealthyUpdater{handler} } -func (m *metricsUpstreamsHealthyUpdater) Init() { +func (m *metricsUpstreamsHealthyUpdater) init() { go func() { defer func() { if err := recover(); err != nil { diff --git a/modules/caddyhttp/reverseproxy/reverseproxy.go b/modules/caddyhttp/reverseproxy/reverseproxy.go index a15dbe42484..d799c5a6e7e 100644 --- a/modules/caddyhttp/reverseproxy/reverseproxy.go +++ b/modules/caddyhttp/reverseproxy/reverseproxy.go @@ -382,8 +382,8 @@ func (h *Handler) Provision(ctx caddy.Context) error { } } - upstreamHealthyUpdater := newMetricsUpstreamsHealthyUpdater(h) - upstreamHealthyUpdater.Init() + upstreamHealthyUpdater := newMetricsUpstreamsHealthyUpdater(h, ctx) + upstreamHealthyUpdater.init() return nil }