Reference server implementation of the gRPC Method Discovery (grpcd) service
This is the canonical Go implementation of the grpcd service as defined in grpcd-protos.
For details on what gRPC Method Discovery is, its architecture, and use cases, see the grpcd-protos documentation.
This implementation demonstrates production-ready patterns for building stateless, horizontally-scalable gRPC services with pluggable storage backends.
Production-ready container images are published to
ghcr.io/sonic-original-software/grpcd
for easy deployment.
- Production Ready: Pre-built container images, OpenTelemetry metrics, structured logging, health checks
- Pluggable Storage: Abstract storage interface with Redis and in-memory implementations
- Peer Context Security: Extracts real client addresses from gRPC peer context to prevent spoofing
- Docker Native: Multi-stage builds, scratch-based images, Docker Compose support
Ready-to-use container images are available at
[]ghcr.io/sonic-original-software/grpcd](https://github.com/sonic-original-software/grpcd/pkgs/container/grpcd).
# Run with in-memory storage (development/testing)
docker run -p 5000:5000 ghcr.io/sonic-original-software/grpcd:latest
# Run with Redis (production)
docker run -p 5000:5000 \
-e STORAGE_BACKEND=redis \
-e STORAGE_ADDRESS=redis:6379 \
ghcr.io/sonic-original-software/grpcd:latestThis is the recommended way to deploy grpcd in production environments.
The easiest way to run grpcd locally with Redis:
docker compose upThis starts:
- Redis on port 6379
- grpcd on port 53001 (mapped to internal port 5000)
Requirements:
- Go 1.25.3 or later
- Redis (optional, for persistent storage)
# Clone the repository
git clone https://github.com/sonic-original-software/grpcd
cd grpcd
# Download dependencies
go mod download
# Build
go build -o grpcd .
# Run with in-memory storage
./grpcd
# Run with Redis storage
STORAGE_BACKEND=redis STORAGE_ADDRESS=localhost:6379 ./grpcdgrpcd is configured entirely through environment variables.
| Variable | Description | Default |
|---|---|---|
GRPC_SERVER_ADDRESS |
Address to bind the gRPC server | :5000 |
| Variable | Description | Default | Required |
|---|---|---|---|
STORAGE_BACKEND |
Storage backend type (redis or empty for in-memory) |
- | No |
STORAGE_ADDRESS |
Storage backend address (format depends on backend) | - | Yes (if using Redis) |
| Variable | Description | Default |
|---|---|---|
REGISTRATION_TTL_MINUTES |
How long registrations remain valid without refresh | 10 |
Development (in-memory storage):
export GRPC_SERVER_ADDRESS=:5000
# No STORAGE_BACKEND set = in-memory storageProduction (Redis storage):
export GRPC_SERVER_ADDRESS=:5000
export STORAGE_BACKEND=redis
export STORAGE_ADDRESS=redis.prod.example.com:6379
export REGISTRATION_TTL_MINUTES=10This server implements the GRPCDService defined in grpcd-protos. For the complete API specification and protobuf definitions, refer to the grpcd-protos repository.
| RPC | Implementation | Notes |
|---|---|---|
Register |
internal/service/register.go:31 |
Extracts real address from peer context for security |
Discover |
internal/service/discover.go:26 |
Returns NOT_FOUND if method is not registered |
Deregister |
internal/service/deregister.go:20 |
Removes all methods for the calling service's address |
The server also implements standard diagnostic services defined in
grpc-protos:
- Info Service:
internal/service/get_info.go - Diagnostics Service:
internal/service/get_diagnostics.go
This implementation uses gRPC peer context to extract the real client address
for Register and Deregister operations. The peer context contains TCP
connection metadata that cannot be spoofed, preventing address hijacking.
See internal/service/register.go:43 and internal/service/deregister.go:26
for implementation details.
grpcd uses an abstract storage interface (internal/storage/store.go:34) that
supports multiple backends.
type Store interface {
SetMethodAddress(ctx, method, address string, ttl time.Duration) error
GetMethodAddress(ctx context.Context, method string) (string, error)
DeleteMethodAddress(ctx context.Context, method string) error
GetMethodsByAddress(ctx context.Context, address string) ([]string, error)
DeleteMethodsByAddress(ctx context.Context, address string) error
Ping(ctx context.Context) error
Name() string
Address() string
}Use Case: Development, testing, single-instance deployments
Characteristics:
- No external dependencies
- Data lost on restart
- Not suitable for production multi-instance deployments
- Automatically selected when
STORAGE_BACKENDis not set
Implementation: internal/storage/mock/
Use Case: Production deployments
Characteristics:
- Persistent storage with optional persistence to disk
- Native TTL support for automatic cleanup
- Horizontal scaling support (all grpcd instances share state)
- High availability with Redis Sentinel or Redis Cluster
Configuration:
STORAGE_BACKEND=redis
STORAGE_ADDRESS=redis-host:6379Implementation: internal/storage/redis/
- Implement the
Storeinterface - Add resolver logic in
internal/storage/resolver/resolve.go
grpcd/
├── main.go # Entry point, server setup
├── internal/
│ ├── service/ # RPC method implementations
│ │ ├── register.go # Register RPC
│ │ ├── discover.go # Discover RPC
│ │ ├── deregister.go # Deregister RPC
│ │ └── server.go # Server type and constructor
│ ├── storage/ # Storage abstraction
│ │ ├── store.go # Store interface
│ │ ├── resolver/ # Backend resolution logic
│ │ ├── mock/ # In-memory implementation
│ │ └── redis/ # Redis implementation
│ └── validate/ # Request validation
├── Dockerfile # Multi-stage Docker build
└── compose.yaml # Local development with Redis
# Run all tests
go test ./...
# Run with coverage
go test -cover ./...
# Run specific package tests
go test ./internal/service/...
# Run fuzz tests
go test -fuzz=FuzzRegister ./internal/service
go test -fuzz=FuzzDiscover ./internal/service# Standard build
go build -o grpcd .
# Optimized build (same as Dockerfile)
CGO_ENABLED=0 go build -ldflags="-w -s" -o grpcd .Major dependencies:
grpcd-protos: Service definition and generated codegrpcd-go: Client library for registering/discovering methodsgrpc-foundation: Common gRPC server utilities and error handlinggrpc-protos: Standard service interfaces (Info, Diagnostics)go-redis/v9: Redis clientgoogle.golang.org/grpc: gRPC frameworkgo.opentelemetry.io/otel: Observability instrumentation
See go.mod for complete list.
The codebase includes:
- Unit tests for all RPC methods
- Fuzz tests for request validation
- Structured logging with contextual information
- OpenTelemetry metrics for monitoring
- Input validation and error handling
See LICENSE file for details.
- grpcd-protos: Protocol buffer definitions and service specification
- grpcd-go: Go client library for gRPC Method Discovery
Contributions welcome! This is the reference implementation, so changes should align with the grpcd specification in grpcd-protos.