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

Dynamic Service Creation and Registration at Runtime. #8156

Open
shaj13 opened this issue Mar 9, 2025 · 0 comments
Open

Dynamic Service Creation and Registration at Runtime. #8156

shaj13 opened this issue Mar 9, 2025 · 0 comments
Assignees
Labels
Area: Server Includes Server, Streams and Server Options. Type: Question

Comments

@shaj13
Copy link

shaj13 commented Mar 9, 2025

I’d like to check whether the following approach is considered best practice and if future releases are unlikely to break it. Additionally, any suggestions or recommendations would be greatly appreciated.

We are designing a system to scrape metrics from multiple replicas (X). The server itself can expose hundreds of metric types, grouping them accordingly, and all metrics will ultimately follow the same format. Our goal is to allow scraping at different intervals for different metrics. In some cases, we may also need to query different servers for specific metric groups and types.

We need a generic or common service interface that all metric services implement.

One possible solution is to generate the gRPC definitions and implement dynamic service registration at runtime based on the available metric services, allowing the client to invoke them accordingly.

syntax = "proto3";

option go_package = "./pb";

import "google/protobuf/empty.proto";

service metrics {
    rpc Scrape(google.protobuf.Empty) returns Resources;
}

message Resources {
    repeated bytes data = 1;
}
import grpc "google.golang.org/grpc"

func RegisterMetricsXServer(s grpc.ServiceRegistrar, srv MetricsServer, ServiceName string) {
	d := grpc.ServiceDesc{
		ServiceName: ServiceName,
		HandlerType: (*MetricsServer)(nil),
		Methods: []grpc.MethodDesc{
			{
				MethodName: "Scrape",
				Handler:    _Metrics_Scrape_Handler,
			},
		},
		Streams:  []grpc.StreamDesc{},
		Metadata: "scrape.proto",
	}

	s.RegisterService(&d, srv)
}
package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net"

	"github.com/golang/protobuf/ptypes/empty"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/protobuf/types/known/emptypb"
)

func main() {
	s := flag.Bool("s", false, "run server")
	flag.Parse()
	if *s {
		if err := server(); err != nil {
			log.Fatal(err)
		}
	}

	for _, m := range []string{"cpu", "memory"} {
		cli(m)
	}

}
func cli(service string) error {
	cc, err := grpc.NewClient(":8080", grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		return err
	}

	in := new(emptypb.Empty)
	out := new(Resources)
	return cc.Invoke(context.Background(), "/"+service+"/Scrape", in, out)
}

func server() error {
	gs := grpc.NewServer(
		grpc.Creds(insecure.NewCredentials()),
	)

	for _, s := range []string{"cpu", "memory"} {
		RegisterMetricsXServer(gs, &service{kind: s}, s)
	}

	l, err := net.Listen("tcp", ":8080")
	if err != nil {
		panic(err)
	}

	fmt.Println("server listen and serve")
	return gs.Serve(l)
}

type service struct {
	kind string
}

func (s *service) Scrape(context.Context, *empty.Empty) (*empty.Empty, error) {
	fmt.Println(s.kind, "called")
	return &emptypb.Empty{}, nil
}

Another approach we are considering is maintaining a single service registration while wrapping the service to route requests to the appropriate implementation based on metadata. Alternatively, we could use an interceptor to direct requests to the relevant handler.

To be honest, I'm inclined toward dynamic service registration and letting go-gRPC handle the logic, as some gRPC gateways and ingress controllers use similar mechanisms, leveraging reflection.

I've encountered #1825, but I couldn't find any reference or example related to it.

@purnesh42H purnesh42H added the Area: Server Includes Server, Streams and Server Options. label Mar 10, 2025
@purnesh42H purnesh42H self-assigned this Mar 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Server Includes Server, Streams and Server Options. Type: Question
Projects
None yet
Development

No branches or pull requests

2 participants