跳到內容

設定

設定檔預設在 etc/config.yaml;檔案不存在時該層被跳過,改用內建預設值加環境變數。其餘載入是 fail-loud:欄位型別錯誤或 secret 不合規,啟動直接失敗而不是帶病上線。

設定由三層疊起來,後者覆寫前者:

  1. 內建預設值(程式碼裡;例如 server.addr:8080cache.drivermemory)。
  2. etc/config.yaml——用 GORTEXA_CONFIG=/path/to/config.yaml 指到別處;檔案不存在時整層跳過。
  3. 環境變數,格式 GORTEXA_<SECTION>__<FIELD>(區塊與欄位之間兩條底線)。

同一個欄位若在多層都設,最後生效的是環境變數。真實 secret 只走環境變數注入,不寫進 config.yaml、不進版控。

server:
addr: ":8080"
shutdown_timeout: 20s
enable_cors: true
cors_origins: [] # CORS allowlist;enable_cors 只是總開關,沒列在這裡的 origin 拿不到 CORS headers
openapi: true
reflection: false # gRPC reflection 預設關
auth:
jwt_secret: "dev-only-insecure-secret-change-me-please"
issuer: "gortexa"
# audience: "myapp" # 選配:設了之後簽出的 token 帶 aud、驗證時要求 aud——隔離共用 secret 的多個服務
ttl: 1h
db:
dsn: "" # PostgreSQL DSN(Secret,日誌遮罩);走環境變數注入:GORTEXA_DB__DSN
max_conns: 10
cache:
driver: "memory" # "memory"(預設,process-local)或 "redis"
mq:
driver: "nats" # "nats"(core,at-most-once)或 "jetstream"(durable,at-least-once)
url: "" # 逗號分隔多 server,例 "nats://a:4222,nats://b:4222"
group_id: "" # 空=fanout;非空=load-balance
log:
level: "info"
format: "json"
observ:
service_name: "gortexa"
service_version: "dev"
# tracing_otlp: "localhost:4317" # OTLP trace endpoint;空值停用
# metrics_otlp: "localhost:4317" # OTLP metrics endpoint;空值停用(rate-limit/circuit-breaker 指標靠它)
# logs_otlp: "localhost:4317" # OTLP log endpoint;空值停用
otlp_insecure: true # 只限本機 docker compose;連遠端一律 false
sample_ratio: 1.0
genai_capture_content: false # 開啟後 MCP tool 呼叫的參數內容會進 telemetry
# genai_mask_fields: ["password", "token", "secret", "authorization", "api_key"]

cache.driver 決定後端。預設 memory 不需要任何外部服務;redis 才讀 addr 以下的欄位。填了 memoryredis 以外的值,啟動會以 cache: unsupported driver 失敗。

cache:
driver: "memory"

Process-local,零外部依賴。適合單機部署與本機開發。

四個 tunable 的零值都代表「用內建預設」,所以只調你要動的那個就好:

欄位 預設 用途
dial_timeout 5s 建立連線的逾時
read_timeout 3s 單次讀取回應的逾時
write_timeout 3s 單次送出命令的逾時
pool_size 10 連線池大小;0 用預設,負值被拒

db.dsn 是 pgx 連線字串(Secret 欄位,日誌一律遮罩);db.max_conns 預設 10。真實 DSN 走環境變數注入:

Terminal window
GORTEXA_DB__DSN=postgres://user:pass@pgbouncer:6432/app

連線池是 PgBouncer-safe 的:QueryExecModeExec、statement 與 description cache 皆關閉,放在 transaction-pooling 模式的 PgBouncer 後面不會因 prepared statement 出錯。

開發流程:schema 放 db/migrations/、SQL 放 db/queries/,跑 make sqlc 產生 type-safe 查詢碼到 internal/storage/db/deploy/docker-compose.yaml 已含 postgres 與 PgBouncer,可供本機驗證。

任何欄位都能用環境變數覆寫,格式 GORTEXA_<SECTION>__<FIELD>

Terminal window
GORTEXA_SERVER__ADDR=:9090
GORTEXA_AUTH__JWT_SECRET=<real-secret>
GORTEXA_CACHE__DRIVER=redis
GORTEXA_CACHE__ADDR=redis.internal:6379
GORTEXA_SERVER__REFLECTION=true
  • config 中的 placeholder dev-only-insecure-secret-change-me-please 會被伺服器拒絕啟動,不可能誤帶上線。
  • JWT secret 長度不足 32 bytes 也會被拒絕。
  • 多個服務共用同一把 secret 與預設 issuer 時,彼此的 token 可以互通——要隔離就各自設 auth.audience(為 A 簽的 token 在 B 會被拒)。
  • redis password、MQ URL(可能內嵌帳密)等 secret 欄位在日誌與錯誤輸出一律遮罩。
  • 真實 secret 走環境變數注入,不進版控。

mq.group_id 決定訊息分派方式,兩個 driver 一致:

group_id NATS(core) JetStream 語意
空(預設) Subscribe ephemeral consumer fanout:每個訂閱者都收到
非空 QueueSubscribe durable consumer(名稱=group_id,handler 成功才 ack) load-balance:一則訊息一個處理者

driver 的差別在投遞保證:core NATS 是 at-most-once(無重投遞,handler 失敗訊息即消失);driver: "jetstream" 是 at-least-once——publish 等 server 落盤確認,handler 回錯誤會延遲重投遞,因此 handler 必須冪等。JetStream 需要 server 以 -js 啟動;框架對每個 topic 惰性自建 stream(保留 24h),operator 也可預建 stream 自訂保留策略——框架只採用、不改寫既有 stream。

Terminal window
gortexa doctor # 檢查 Go toolchain 與 proto 工具