Skip to content
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

[vtadmin] Add support for additional service healthchecks in grpcserver #7635

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions go/vt/vtadmin/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ type API struct {

// NewAPI returns a new API, configured to service the given set of clusters,
// and configured with the given gRPC and HTTP server options.
//
// If opts.Services is nil, NewAPI will automatically add
// "vtadmin.VTAdminServer" to the list of services queryable in the healthcheck
// service. Callers can opt-out of this behavior by explicitly setting this
// value to the empty slice.
func NewAPI(clusters []*cluster.Cluster, opts grpcserver.Options, httpOpts vtadminhttp.Options) *API {
clusterMap := make(map[string]*cluster.Cluster, len(clusters))
for _, cluster := range clusters {
Expand All @@ -68,6 +73,10 @@ func NewAPI(clusters []*cluster.Cluster, opts grpcserver.Options, httpOpts vtadm
return c1.ID < c2.ID
}).Sort(clusters)

if opts.Services == nil {
opts.Services = []string{"vtadmin.VTAdminServer"}
}

serv := grpcserver.New("vtadmin", opts)
serv.Router().HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok\n"))
Expand Down
28 changes: 25 additions & 3 deletions go/vt/vtadmin/grpcserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,23 @@ type Options struct {
// EnableTracing specifies whether to install opentracing interceptors on
// the gRPC server.
EnableTracing bool
// Services is a list of service names to declare as SERVING in health
// checks. Names should be fully-qualified (package_name.service_name, e.g.
// vtadmin.VTAdminServer, not VTAdminServer), and must be unique for a
// single Server instance. Users of this package are responsible for
// ensuring they do not pass a list with duplicate service names.
//
// The service name "grpc.health.v1.Health" is reserved by this package in
// order to power the healthcheck service. Attempting to pass this in the
// Services list to a grpcserver will be ignored.
//
// See https://github.com/grpc/grpc/blob/7324556353e831c57d30973db33df489c3ed3576/doc/health-checking.md
// for more details on healthchecking.
Services []string
}

const healthServiceName = "grpc.health.v1.Health" // reserved health service name

// Server provides a multiplexed gRPC/HTTP server.
type Server struct {
name string
Expand Down Expand Up @@ -201,9 +216,16 @@ func (s *Server) ListenAndServe() error { // nolint:funlen
shutdown <- err
}()

// (TODO:@amason) Figure out a good abstraction to have other services
// register themselves.
s.healthServer.SetServingStatus("grpc.health.v1.Health", healthpb.HealthCheckResponse_SERVING)
s.healthServer.SetServingStatus(healthServiceName, healthpb.HealthCheckResponse_SERVING)

for _, name := range s.opts.Services {
if name == healthServiceName {
log.Warningf("Attempted to register a service under the reserved healthcheck service name %s; ignoring", healthServiceName)
continue
}

s.healthServer.SetServingStatus(name, healthpb.HealthCheckResponse_SERVING)
}

s.setServing(true)
log.Infof("server %s listening on %s", s.name, s.opts.Addr)
Expand Down