Files
lijiaoqiao/platform-token-runtime/internal/app/bootstrap.go
Your Name ae2b1bfe75 P3-A: Token Runtime 缓存层实现 - HTTPTimeout/LRU淘汰/命中率指标
Phase 3-A 完整实现,包含:

Gateway (lijiaoqiao/gateway):
- RemoteTokenRuntime 缓存实现: active=30s/expired=2m/revoked=10m TTL淘汰
- LRU 容量淘汰 (max_entries=10000,插入顺序淘汰)
- HTTPTimeoutConfig: 4个环境变量 (Dial/KeepAlive/Read/Write/MaxIdle)
- 缓存命中率指标: GetCacheHitRate() + 实例级别统计
- 上游延迟指标: RecordTokenRuntime() histogram
- buildTimeoutClient: 基于 HTTPTimeoutConfig 的 HTTP 客户端工厂
- 新增测试: 22个矩阵测试 (remote_runtime_matrix_test.go, config_test.go)

Platform Token Runtime (lijiaoqiao/platform-token-runtime):
- metrics/metrics.go: GetCacheHitRate() 方法
- inmemory_runtime.go: GetCacheHitRate() 实现

变更文件 (8 modified + 5 new):
- gateway/internal/middleware/remote_runtime.go    # 核心缓存实现
- gateway/internal/middleware/remote_runtime_test.go
- gateway/internal/middleware/remote_runtime_cache_test.go
- gateway/internal/middleware/remote_runtime_matrix_test.go
- gateway/internal/middleware/remote_runtime_metrics_test.go
- gateway/internal/metrics/metrics.go             # 新增
- gateway/internal/config/config.go                # HTTPTimeoutConfig
- gateway/internal/config/config_test.go
- gateway/internal/app/bootstrap.go                # 初始化顺序
- gateway/internal/router/router.go                # 指标注入
- platform-token-runtime/internal/metrics/metrics.go  # 新增
- platform-token-runtime/internal/app/bootstrap.go
- platform-token-runtime/internal/auth/service/inmemory_runtime.go
2026-04-21 17:27:51 +08:00

118 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package app
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/jackc/pgx/v5/pgxpool"
"lijiaoqiao/platform-token-runtime/internal/auth/service"
"lijiaoqiao/platform-token-runtime/internal/httpapi"
met "lijiaoqiao/platform-token-runtime/internal/metrics"
)
type Config struct {
Addr string
Env string
RuntimeStore service.RuntimeStore
AuditStore service.AuditStore
Now func() time.Time
}
var newPostgresStoreBundle = func(ctx context.Context, databaseURL string) (service.RuntimeStore, service.AuditStore, func(), error) {
if ctx == nil {
ctx = context.Background()
}
pool, err := pgxpool.New(ctx, strings.TrimSpace(databaseURL))
if err != nil {
return nil, nil, nil, err
}
if err := pool.Ping(ctx); err != nil {
pool.Close()
return nil, nil, nil, err
}
return service.NewPostgresRuntimeStore(pool), service.NewPostgresAuditStore(pool), pool.Close, nil
}
func BuildPostgresStores(ctx context.Context, databaseURL string) (service.RuntimeStore, service.AuditStore, func(), error) {
if strings.TrimSpace(databaseURL) == "" {
return nil, nil, nil, fmt.Errorf("token runtime database url is required")
}
return newPostgresStoreBundle(ctx, databaseURL)
}
func BuildRuntime(cfg Config) (*service.InMemoryTokenRuntime, service.AuditStore, error) {
now := cfg.Now
if now == nil {
now = time.Now
}
env := strings.ToLower(strings.TrimSpace(cfg.Env))
runtimeStore := cfg.RuntimeStore
auditStore := cfg.AuditStore
switch env {
case "", "dev":
if runtimeStore == nil {
runtimeStore = service.NewInMemoryRuntimeStore()
}
if auditStore == nil {
auditStore = service.NewMemoryAuditStore()
}
case "prod", "staging":
if runtimeStore == nil {
return nil, nil, fmt.Errorf("runtime store is required in %s", env)
}
if auditStore == nil {
return nil, nil, fmt.Errorf("audit store is required in %s", env)
}
default:
return nil, nil, fmt.Errorf("unsupported TOKEN_RUNTIME_ENV %q", cfg.Env)
}
return service.NewInMemoryTokenRuntimeWithStore(now, runtimeStore), auditStore, nil
}
func BuildServer(cfg Config) (*http.Server, error) {
now := cfg.Now
if now == nil {
now = time.Now
}
addr := strings.TrimSpace(cfg.Addr)
if addr == "" {
addr = ":18081"
}
runtime, auditor, err := BuildRuntime(cfg)
if err != nil {
return nil, err
}
api := httpapi.NewTokenAPI(runtime, auditor, now)
mux := http.NewServeMux()
mux.HandleFunc("/actuator/health", func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(`{"status":"UP"}`))
})
// P3-B: /metrics 端点Prometheus-text 格式)
mux.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain; version=0.0.4")
_, _ = w.Write([]byte(met.Export()))
})
api.Register(mux)
return &http.Server{
Addr: addr,
Handler: mux,
ReadHeaderTimeout: 5 * time.Second,
ReadTimeout: 10 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 30 * time.Second,
}, nil
}