跳到內容

核心

先取得模組:go get github.com/yshengliao/gortexa@v0.27.0。以下片段皆對 v0.27.0 編譯驗證過。

composition root:App 擁有單一 h2c listener(多工 gRPC、HTTP/JSON、MCP)、gRPC server、health registry、in-process loopback 與 graceful shutdown。用 kernel.New(opts...) 建立,options 有 WithConfigWithLoggerWithInterceptors(吃 interceptor.Set 值,非指標)、WithStatsHandlerWithHTTPWrapWithGatewayWithMCPHandlerWithShutdownHookWithServerOptions(append gRPC ServerOption,讓你加自己的 interceptor/stats,接在框架鏈之後)、WithAdminListener(opt-in 獨立 ops 埠只服務 /healthz+/readyz)、WithExtraListener(在 caller 自有 listener 上服務任意 handler)。主 h2c 埠始終單埠多工不變;app.AdminAddr() 可查 admin 埠實綁位址。

import (
"context"
"github.com/yshengliao/gortexa/config"
"github.com/yshengliao/gortexa/health"
"github.com/yshengliao/gortexa/kernel"
)
cfg := config.MustBuild()
app, err := kernel.New(kernel.WithConfig(cfg))
if err != nil {
return err
}
// 在此把 gRPC service 註冊到 app.GRPCServer()
app.Health().Register("self", func(context.Context) health.State { return health.Healthy })
return app.Run(ctx) // /healthz、/readyz 內建

App 的方法:GRPCServer()Health()Loopback()Logger()SetGateway()SetMCPHandler()Run(ctx)Shutdown(ctx)

固定優先序:內建預設 < YAML 檔 < .env 檔 < 環境變數(GORTEXA_ 前綴、__ 表巢狀)。入口是 MustBuild(fail-loud,jwt_secret 為空/預設 placeholder/< 32 bytes 或 issuer 空會 panic)與 BuildUnvalidated。沒有 Load

import "github.com/yshengliao/gortexa/config"
cfg := config.MustBuild(config.WithConfigFile("etc/config.yaml"))
dsn := cfg.DB.DSN.Reveal() // Secret 只在使用點還原

secret 型別 config.SecretString()/log/JSON 一律遮罩成 ****,要真值用 Reveal()Config 的子結構:ServerAuthDBCacheMQLogObserv(全欄位見設定)。

NewSet(Config) 產出八段固定順序的鏈(recover → request-id → logger → load-shed → rate-limit → circuit-breaker → auth → validation),交給 kernel.WithInterceptors

import (
"time"
"github.com/yshengliao/gortexa/auth"
"github.com/yshengliao/gortexa/interceptor"
)
set, err := interceptor.NewSet(interceptor.Config{
Verifier: auth.MustNewVerifier([]byte(secret), "gortexa"),
RateLimit: interceptor.RateLimitConfig{RPS: 200, Burst: 100, TTL: 10 * time.Minute},
})
// set 傳給 kernel.WithInterceptors(set)

Config 另有 LoggerAuthSkipCircuitBreakerLoadSheddingMetrics 欄位。Set 提供 UnaryChain()StreamChain()

auth 段可插拔:Verifier 走內建 HS256 JWT;非 JWT 方案改設 Authenticator(一個 auth.AuthenticatorAuthenticate(ctx) (ctx, error)),例如 static bearer/mTLS/API-key。兩者都設時 Authenticator 優先。JWT 也可用 auth.NewJWTAuthenticator(v) 顯式取得。

HS256 JWT 驗證/簽發與 context helper。secret 須 ≥ 32 bytes。

import "github.com/yshengliao/gortexa/auth"
v := auth.MustNewVerifier([]byte(secret), "gortexa")
tok, err := v.Sign("user-123", []string{"admin"}, time.Hour)
// 在 handler 內取回驗證過的 claims:
if claims, ok := auth.ClaimsFrom(ctx); ok {
_ = claims.Subject // "user-123"
}

Verify(token)*Claims(含 Roles 與內嵌的 jwt.RegisteredClaims);BearerToken(header) 從 Authorization header 取 token。

單一對應表驅動 gRPC status、HTTP status 與 MCP error envelope。*apperr.Error 實作了 GRPCStatus(),handler 直接回傳即可。

import "github.com/yshengliao/gortexa/apperr"
func (s *svc) GetThing(ctx context.Context, req *pb.GetThingRequest) (*pb.Thing, error) {
t, err := s.repo.Find(ctx, req.GetId())
if err != nil {
return nil, apperr.Wrap(apperr.CatNotFound, "thing not found", err)
}
return t, nil
}

只有 CatInvalidArgumentCatUnauthenticated 會把開發者訊息轉給呼叫端;其餘 category 只露出 registry 的 SafeMessage,內部原因不外洩。category 常數涵蓋 gRPC 的完整清單(CatNotFoundCatPermissionDeniedCatFailedPreconditionCatInternal 等)。