-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Enable refactoring queue-proxy binary with out-of-tree extensions #13133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
ecee81c
c5a8030
bddc07e
e98327f
dbcf283
9a4d6d9
5137f03
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,12 +92,6 @@ type config struct { | |
ServingEnableProbeRequestLog bool `split_words:"true"` // optional | ||
|
||
// Metrics configuration | ||
ServingNamespace string `split_words:"true" required:"true"` | ||
ServingRevision string `split_words:"true" required:"true"` | ||
ServingConfiguration string `split_words:"true" required:"true"` | ||
ServingPodIP string `split_words:"true" required:"true"` | ||
ServingPod string `split_words:"true" required:"true"` | ||
ServingService string `split_words:"true"` // optional | ||
ServingRequestMetricsBackend string `split_words:"true"` // optional | ||
MetricsCollectorAddress string `split_words:"true"` // optional | ||
|
||
|
@@ -110,23 +104,46 @@ type config struct { | |
// Concurrency State Endpoint configuration | ||
ConcurrencyStateEndpoint string `split_words:"true"` // optional | ||
ConcurrencyStateTokenPath string `split_words:"true"` // optional | ||
|
||
Env | ||
} | ||
|
||
type Env struct { | ||
ServingNamespace string `split_words:"true" required:"true"` | ||
ServingRevision string `split_words:"true" required:"true"` | ||
ServingConfiguration string `split_words:"true" required:"true"` | ||
ServingPodIP string `split_words:"true" required:"true"` | ||
ServingPod string `split_words:"true" required:"true"` | ||
ServingService string `split_words:"true"` // optional | ||
|
||
} | ||
|
||
type Defaults struct { | ||
Ctx context.Context | ||
Logger *zap.SugaredLogger | ||
Transport http.RoundTripper | ||
Env Env | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I'm wondering if I suspect not. I'm also wondering about the name... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This list includes two parts:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wouldn't split, I'd just note in comments which ones are considered mutable and which ones aren't. Since they're exported types, an overview comment on the |
||
|
||
type Option func(*Defaults) | ||
|
||
func init() { | ||
maxprocs.Set() | ||
} | ||
|
||
func Main() { | ||
ctx := signals.NewContext() | ||
func Main(opts ...Option) error { | ||
davidhadas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
d := Defaults{ | ||
Ctx: signals.NewContext(), | ||
} | ||
|
||
// Parse the environment. | ||
var env config | ||
if err := envconfig.Process("", &env); err != nil { | ||
fmt.Fprintln(os.Stderr, err) | ||
dprotaso marked this conversation as resolved.
Show resolved
Hide resolved
|
||
os.Exit(1) | ||
return err | ||
} | ||
|
||
// Setup the logger. | ||
d.Env = env.Env | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can see that you're slicing the "where I'm at" out of the larger configuration. I'm wondering whether we should simply pass along all the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could enable splitting out There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This ensures that extensions receive a copy of the Env and cannot change the Env used by the service which I think is appropriate here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think just having a read-only |
||
|
||
// Setup the Logger. | ||
logger, _ := pkglogging.NewLogger(env.ServingLoggingConfig, env.ServingLoggingLevel) | ||
defer flush(logger) | ||
|
||
|
@@ -137,8 +154,16 @@ func Main() { | |
}.String()), | ||
zap.String(logkey.Pod, env.ServingPod)) | ||
|
||
d.Logger = logger | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not put this on 147? Reducing code movement? I'd be inclined to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This ensures that extensions receive a copy of the logger and cannot change the logger used by the service which I think is appropriate here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm ok either way. Longer term I would expect the logger be pluggable in the future func WithLogger(l *zap.SugaredLogger) func(q *Defaults) {
return func(d *Defaults) {
d.Logger = l
return
}
} |
||
d.Transport = buildTransport(env, logger) | ||
|
||
// allow extensions to read d and return modified context and transport | ||
for _, opts := range opts { | ||
opts(&d) | ||
} | ||
|
||
// Report stats on Go memory usage every 30 seconds. | ||
metrics.MemStatsOrDie(ctx) | ||
metrics.MemStatsOrDie(d.Ctx) | ||
|
||
protoStatReporter := queue.NewProtobufStatsReporter(env.ServingPod, reportingPeriod) | ||
|
||
|
@@ -169,7 +194,7 @@ func Main() { | |
// Enable TLS when certificate is mounted. | ||
tlsEnabled := exists(logger, certPath) && exists(logger, keyPath) | ||
|
||
mainServer, drain := buildServer(ctx, env, probe, stats, logger, concurrencyendpoint, false) | ||
mainServer, drain := buildServer(d.Ctx, env, d.Transport, probe, stats, logger, concurrencyendpoint, false) | ||
httpServers := map[string]*http.Server{ | ||
"main": mainServer, | ||
"metrics": buildMetricsServer(protoStatReporter), | ||
|
@@ -184,7 +209,7 @@ func Main() { | |
// See also https://github.com/knative/serving/issues/12808. | ||
var tlsServers map[string]*http.Server | ||
if tlsEnabled { | ||
mainTLSServer, drain := buildServer(ctx, env, probe, stats, logger, concurrencyendpoint, true /* enable TLS */) | ||
mainTLSServer, drain := buildServer(d.Ctx, env, d.Transport, probe, stats, logger, concurrencyendpoint, true /* enable TLS */) | ||
tlsServers = map[string]*http.Server{ | ||
"tlsMain": mainTLSServer, | ||
"tlsAdmin": buildAdminServer(logger, drain), | ||
|
@@ -220,10 +245,8 @@ func Main() { | |
select { | ||
case err := <-errCh: | ||
logger.Errorw("Failed to bring up queue-proxy, shutting down.", zap.Error(err)) | ||
// This extra flush is needed because defers are not handled via os.Exit calls. | ||
flush(logger) | ||
os.Exit(1) | ||
case <-ctx.Done(): | ||
return err | ||
case <-d.Ctx.Done(): | ||
if env.ConcurrencyStateEndpoint != "" { | ||
concurrencyendpoint.Terminating(logger) | ||
} | ||
|
@@ -242,6 +265,7 @@ func Main() { | |
} | ||
logger.Info("Shutdown complete, exiting...") | ||
} | ||
return nil | ||
} | ||
|
||
func exists(logger *zap.SugaredLogger, filename string) bool { | ||
|
@@ -263,14 +287,14 @@ func buildProbe(logger *zap.SugaredLogger, encodedProbe string, autodetectHTTP2 | |
return readiness.NewProbe(coreProbe) | ||
} | ||
|
||
func buildServer(ctx context.Context, env config, probeContainer func() bool, stats *netstats.RequestStats, logger *zap.SugaredLogger, | ||
func buildServer(ctx context.Context, env config, transport http.RoundTripper, probeContainer func() bool, stats *netstats.RequestStats, logger *zap.SugaredLogger, | ||
ce *queue.ConcurrencyEndpoint, enableTLS bool) (server *http.Server, drain func()) { | ||
// TODO: If TLS is enabled, execute probes twice and tracking two different sets of container health. | ||
|
||
target := net.JoinHostPort("127.0.0.1", env.UserPort) | ||
|
||
httpProxy := pkghttp.NewHeaderPruningReverseProxy(target, pkghttp.NoHostOverride, activator.RevisionHeaders, false /* use HTTP */) | ||
httpProxy.Transport = buildTransport(env, logger) | ||
httpProxy.Transport = transport | ||
httpProxy.ErrorHandler = pkghandler.Error(logger) | ||
httpProxy.BufferPool = netproxy.NewBufferPool() | ||
httpProxy.FlushInterval = netproxy.FlushInterval | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should also probably log the error here
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we let downstream change this file, I think it is best if we log inside sharedmain to ensure consistent logging.