-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pgwire: create a framework for pre-serve connection logic
This commit introduces `PreServeConnHandler`, which will handle the preparation of a SQL connection prior to handing it off to a specific tenant server. Release note (ops changes): The count of network bytes sent to report re-authentication errors to a SQL client is now reported via the metric `sql.pre_serve.bytesout` (instead of `sql.bytesout` previously). The count of pre-authentication errors is now reported via the metric `sql.pre_serve.conn.failures` (instead of `sql.conn.failures` previously). Release note (ops changes): The count of new SQL connections is now also reported on `sql.pre_serve.new_conns`.
- Loading branch information
Showing
4 changed files
with
170 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
// Copyright 2022 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
package pgwire | ||
|
||
import ( | ||
"context" | ||
"net" | ||
|
||
"github.com/cockroachdb/cockroach/pkg/settings" | ||
"github.com/cockroachdb/cockroach/pkg/util/metric" | ||
) | ||
|
||
// Fully-qualified names for metrics. | ||
var ( | ||
MetaPreServeNewConns = metric.Metadata{ | ||
Name: "sql.pre_serve.new_conns", | ||
Help: "Counter of the number of SQL connections created prior to routine the connection a specific tenant", | ||
Measurement: "Connections", | ||
Unit: metric.Unit_COUNT, | ||
} | ||
MetaPreServeBytesIn = metric.Metadata{ | ||
Name: "sql.pre_serve.bytesin", | ||
Help: "Number of SQL bytes received prior to routing the connection to a specific tenant", | ||
Measurement: "SQL Bytes", | ||
Unit: metric.Unit_BYTES, | ||
} | ||
MetaPreServeBytesOut = metric.Metadata{ | ||
Name: "sql.pre_serve.bytesout", | ||
Help: "Number of SQL bytes sent prior to routing the connection to a specific tenant", | ||
Measurement: "SQL Bytes", | ||
Unit: metric.Unit_BYTES, | ||
} | ||
MetaPreServeConnFailures = metric.Metadata{ | ||
Name: "sql.pre_serve.conn.failures", | ||
Help: "Number of SQL connection failures prior to routing the connection to a specific tenant", | ||
Measurement: "Connections", | ||
Unit: metric.Unit_COUNT, | ||
} | ||
) | ||
|
||
// PreServeConnHandler implements the early initialization of an incoming | ||
// SQL connection, before it is routed to a specific tenant. It is | ||
// tenant-independent, and thus cannot rely on tenant-specific connection | ||
// or state. | ||
type PreServeConnHandler struct { | ||
errWriter errWriter | ||
tenantIndependentMetrics tenantIndependentMetrics | ||
} | ||
|
||
// MakePreServeConnHandler creates a PreServeConnHandler. | ||
// sv refers to the setting values "outside" of the current tenant - i.e. from the storage cluster. | ||
func MakePreServeConnHandler(sv *settings.Values) PreServeConnHandler { | ||
metrics := makeTenantIndependentMetrics() | ||
return PreServeConnHandler{ | ||
errWriter: errWriter{ | ||
sv: sv, | ||
msgBuilder: newWriteBuffer(metrics.PreServeBytesOutCount), | ||
}, | ||
tenantIndependentMetrics: metrics, | ||
} | ||
} | ||
|
||
// tenantIndependentMetrics is the set of metrics for the | ||
// pre-serve part of connection handling, before the connection | ||
// is routed to a specific tenant. | ||
type tenantIndependentMetrics struct { | ||
PreServeBytesInCount *metric.Counter | ||
PreServeBytesOutCount *metric.Counter | ||
PreServeConnFailures *metric.Counter | ||
PreServeNewConns *metric.Counter | ||
} | ||
|
||
func makeTenantIndependentMetrics() tenantIndependentMetrics { | ||
return tenantIndependentMetrics{ | ||
PreServeBytesInCount: metric.NewCounter(MetaPreServeBytesIn), | ||
PreServeBytesOutCount: metric.NewCounter(MetaPreServeBytesOut), | ||
PreServeNewConns: metric.NewCounter(MetaPreServeNewConns), | ||
PreServeConnFailures: metric.NewCounter(MetaPreServeConnFailures), | ||
} | ||
} | ||
|
||
// Metrics returns the set of metrics structs. | ||
func (s *PreServeConnHandler) Metrics() (res []interface{}) { | ||
return []interface{}{&s.tenantIndependentMetrics} | ||
} | ||
|
||
// sendErr sends errors to the client during the connection startup | ||
// sequence. Later error sends during/after authentication are handled | ||
// in conn.go. | ||
func (s *PreServeConnHandler) sendPreServeErr(ctx context.Context, conn net.Conn, err error) error { | ||
// We could, but do not, report server-side network errors while | ||
// trying to send the client error. This is because clients that | ||
// receive error payload are highly correlated with clients | ||
// disconnecting abruptly. | ||
_ /* err */ = s.errWriter.writeErr(ctx, err, conn) | ||
_ = conn.Close() | ||
return err | ||
} | ||
|
||
// PreServe serves a single connection, up to and including the | ||
// point status parameters are read from the client (which happens | ||
// pre-authentication). This logic is tenant-independent. Once the | ||
// status parameters are known, the connection can be routed to a | ||
// particular tenant. | ||
func (s *PreServeConnHandler) PreServe( | ||
ctx context.Context, conn net.Conn, socketType SocketType, | ||
) (err error) { | ||
defer func() { | ||
if err != nil { | ||
s.tenantIndependentMetrics.PreServeConnFailures.Inc(1) | ||
} | ||
}() | ||
s.tenantIndependentMetrics.PreServeNewConns.Inc(1) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters