Skip to content

grpc_en.md

maoxiaoyue edited this page May 14, 2026 · 1 revision

pkg/grpc -- gRPC Server Wrapper

v0.8.5+ This package is a new feature added in HypGo v0.8.5 and is not available in v0.8.1.

The grpc package provides a unified gRPC Server wrapper, including listener management, TLS, reflection, health check, interceptors (middleware), and graceful shutdown.

Design Philosophy

HypGo's gRPC and REST use an independent Server architecture:

pkg/server   -> HTTP/1.1 + HTTP/2 + HTTP/3 (REST + WebSocket)  :8080
pkg/grpc     -> gRPC Server                                     :9090

Both share:
  app/models/     <- Data structures
  app/services/   <- Business logic
  pkg/errors/     <- Error Catalog
  pkg/hidb/       <- Database
  pkg/logger/     <- Logging
  pkg/config/     <- Configuration

Quick Start

Create a gRPC Project

hyp new grpc userservice && cd userservice && go mod tidy
make proto    # Compile .proto -> Go code
go run .

Add gRPC to an Existing Project

import (
    hypgrpc "github.com/maoxiaoyue/hypgo/pkg/grpc"
    "github.com/maoxiaoyue/hypgo/pkg/grpc/interceptor"
)

grpcSrv := hypgrpc.New(hypgrpc.Config{
    Addr:              ":9090",
    EnableReflection:  true,
    EnableHealthCheck: true,
}, logger,
    grpc.ChainUnaryInterceptor(
        interceptor.Recovery(logger),
        interceptor.Logger(logger),
    ),
)

// Register services
pb.RegisterUserServiceServer(grpcSrv.GRPCServer(), &UserServer{})

// Start
go grpcSrv.Start()

// Graceful shutdown
grpcSrv.GracefulStop()

Config

type Config struct {
    Addr              string      // Listen address (default ":9090")
    TLS               *TLSConfig  // TLS configuration (nil = plaintext)
    EnableReflection  bool        // Enable gRPC reflection (grpcurl debugging)
    EnableHealthCheck bool        // Enable gRPC health check service
    MaxRecvMsgSize    int         // Maximum receive message size (default 4MB)
    MaxSendMsgSize    int         // Maximum send message size (default 4MB)
}

type TLSConfig struct {
    CertFile string
    KeyFile  string
}

Server API

Method Description
New(cfg, logger, ...grpc.ServerOption) Create Server (auto-configures TLS, reflection, health)
GRPCServer() Get underlying *grpc.Server (for pb.RegisterXxxServer)
Start() Start (blocking)
GracefulStop() Graceful shutdown (waits for in-flight RPCs to complete)
Stop() Immediate stop
Addr() Get actual listen address
IsShuttingDown() Whether shutdown is in progress (atomic.Bool)
SetServingStatus(service, status) Set health check status

Interceptors (gRPC Middleware)

Corresponding to pkg/middleware/ HTTP middleware:

Interceptor Function Corresponding HTTP middleware
interceptor.Recovery(logger) Panic -> codes.Internal middleware.Recovery
interceptor.Logger(logger) Logs method, duration, status code middleware.Logger
interceptor.Auth(authFn, skipMethods...) Token validation + context injection middleware.JWT
interceptor.RateLimit(config) IP rate limiting + background cleanup middleware.RateLimit

Using Interceptors

s := hypgrpc.New(cfg, logger,
    grpc.ChainUnaryInterceptor(
        interceptor.Recovery(logger),                    // Outermost: catch panics
        interceptor.Logger(logger),                      // Log each RPC
        interceptor.Auth(myAuthFunc,                     // Validate token
            "/grpc.health.v1.Health/Check",              // Skip health check
        ),
        interceptor.RateLimit(interceptor.RateLimitConfig{
            MaxRequests: 100,                            // 100 per minute
            Window:      time.Minute,
        }),
    ),
)

Auth Interceptor Details

// Define validation function
authFn := func(ctx context.Context, token string) (interface{}, error) {
    // Validate JWT token
    claims, err := jwt.Validate(token)
    if err != nil {
        return nil, err  // -> codes.Unauthenticated
    }
    return claims, nil  // Stored in context
}

// Extract user in RPC handler
func (s *Server) GetUser(ctx context.Context, req *pb.GetUserReq) (*pb.UserResp, error) {
    user, ok := interceptor.UserFromContext(ctx)
    if !ok {
        return nil, status.Error(codes.Internal, "no user in context")
    }
    // user is the object returned by authFn
}

RateLimit Security Design

  • Rate limits by client IP (obtained from peer.FromContext)
  • Background goroutine periodically cleans up expired keys (default every 5 minutes)
  • Returns codes.ResourceExhausted when limit is exceeded

Project Structure

hyp new grpc userservice
userservice/
├── app/
│   ├── proto/userservicepb/
│   │   └── userservice.proto      <- Protobuf definitions
│   ├── rpc/
│   │   └── userservice_server.go  <- gRPC service implementation
│   ├── models/                    <- Shared data structures
│   ├── services/                  <- Shared business logic
│   └── config/config.yaml
├── main.go
├── Makefile                       <- make proto
└── go.mod

Adding More Services

hyp generate proto order
# -> app/proto/orderpb/order.proto
# -> app/rpc/order_server.go

Coexistence with REST

The same project can have both REST and gRPC:

func main() {
    // REST Server
    srv := server.New(cfg, log)
    routers.Setup(srv.Router())

    // gRPC Server
    grpcSrv := hypgrpc.New(hypgrpc.Config{Addr: ":9090"}, log)
    pb.RegisterUserServiceServer(grpcSrv.GRPCServer(), &UserServer{})

    // Start both simultaneously
    go srv.Start()    // :8080 REST
    go grpcSrv.Start() // :9090 gRPC

    // Graceful shutdown
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    <-quit

    srv.Shutdown(ctx)
    grpcSrv.GracefulStop()
}

Shared Service Layer

Controller (REST)  -+
                    +-> UserService (app/services/)  ->  Database
RPC Handler (gRPC) -+

Controllers and RPC handlers are thin adapters; the actual logic is shared in app/services/.

Security

  • TLS: Supports mTLS, MinVersion = TLS 1.2
  • Auth: No token provided -> codes.Unauthenticated (secure default)
  • Auth skip: Can skip methods that don't require authentication (e.g., Health check)
  • RateLimit: Background cleanup prevents memory leaks
  • Recovery: Panics don't crash, returns codes.Internal
  • GracefulStop: atomic.Bool prevents duplicate shutdown

Required Tools

gRPC development requires:

# protoc compiler
# https://github.com/protocolbuffers/protobuf/releases

# Go protobuf plugins
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

# Debugging tool (optional)
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest

HypGo

繁體中文 | English


中文文件

設計文件

套件

AI 協作工具鏈

CLI 命令


English Docs

Design Docs

Packages

AI Collaboration Toolchain

CLI Commands

Clone this wiki locally