← 返回文章列表

基礎設施(golang)

梳理 Go 服務開發涉及的基礎設施與常見元件。

寫 Go 服務的時候,業務程式碼只是一部分。資料存在哪裡,配置怎麼讀,出問題之後去哪找日誌,這些也得提前想好。這裡把這些基礎元件放到一條請求裡看,方便後面做專案時對照。

基礎設施是什麼?

簡單理解,就是業務背後那些反覆會用到的支撐能力。比如做一個任務清單,建立任務是業務;儲存任務的資料庫、登入狀態、日誌、部署和備份,則是在支撐業務執行。

基礎設施和微服務框架也不是一回事。Kratos、go-zero 主要組織服務程式碼和接入元件;MySQL、Redis、訊息佇列是獨立的系統。用了框架,還是得理解這些元件各自負責什麼。

一個請求會經過哪些地方?

以“新增任務”為例:

浏览器 → HTTP 接口 → 参数校验 → 业务逻辑 → 数据库 → 响应
                           ↓
                    日志、指标、链路记录

最小版本可以只有一個 Go 程序和一個資料庫。先把引數校驗、錯誤返回、超時和資料儲存做對。快取、佇列、服務發現,要等出現明確需求再接。

常見元件怎麼分工?

元件解決什麼問題接入時先看什麼
配置區分本地、測試和生產環境預設值、必填項、敏感配置來源
資料庫儲存需要長期保留的資料約束、索引、事務、連線池
快取減少重複查詢,儲存可丟失的臨時結果過期時間、失效時機、資料一致性
訊息佇列把較慢的工作從請求中拆出去消費重試、重複訊息、積壓
服務發現根據服務名找到可用例項健康狀態、地址變化、呼叫超時
可觀測性看清服務是否正常,以及哪裡出了問題日誌、指標、鏈路之間的關聯

資料庫:先把正確性做出來

任務標題不能是空的,任務 ID 不能重複,這類約束儘量也放到資料庫裡。一次業務操作涉及多次寫入時,要考慮能否用事務保持一致。MySQL 的事務與鎖可以從 InnoDB 文件開始看。

另外,資料庫連線不是開得越多越好。連線池上限需要結合資料庫容量和請求耗時設定,查詢也要有超時。Go 中可以把請求的 context.Context 傳給 QueryContext、ExecContext,具體用法見 取消資料庫操作。

快取:別把它當成第二份隨便寫的資料庫

例如任務詳情采用“先讀快取,未命中再查資料庫”的方式,那麼更新任務之後,舊快取就要處理。先把快取失效的規則寫清楚,再考慮效能。

Redis 的 Go 客戶端可以看 go-redis 官方用法。客戶端應按應用生命週期複用,別每個 HTTP 請求都重新建立一個。

訊息佇列:非同步以後,問題並沒有消失

發通知、生成報告之類的工作,可以先記錄任務,再交給後臺消費。這裡最容易漏掉的是重複執行:同一條訊息因為重試被消費兩次,業務還能不能正確?一般需要業務 ID、狀態約束或其他冪等措施。

如果只是一個低頻的小工具,同步執行或者一個簡單的後臺任務可能就夠了。多引入一個元件,也就多一份部署、監控和故障處理工作。

日誌、指標和鏈路,各看什麼?

  • 日誌:這次請求發生了什麼,錯誤在哪裡。
  • 指標:最近錯誤率有沒有上升,耗時和佇列長度有沒有異常。
  • 鏈路:一次請求跨了哪些呼叫,時間主要花在哪裡。

這幾類資訊可以用 request ID 或 trace ID 聯絡起來。它們的用途可以參考 OpenTelemetry 的訊號說明。日誌裡記錄必要的上下文,不要直接把密碼、令牌或完整使用者資料打出來。

在專案裡怎麼組織?

一個小專案可以先這樣分:

cmd/server/           程序入口,组装依赖,启动和退出
internal/service/     接口层,转换请求和响应
internal/biz/         业务规则
internal/data/        数据库、缓存等访问实现
configs/              可以公开的配置示例

這是一種組織方式,不是所有專案都必須照著建。只有一個簡單介面時,也不需要為每個函式都造一層介面。重點是業務規則不要被某個資料庫客戶端綁死,資源的建立和關閉也要能找到。

上線之前過一遍

我更傾向於按實際請求去檢查:錯誤輸入有沒有被攔住,資料庫慢下來之後有沒有超時,程式退出時有沒有停止接收請求,備份能不能恢復,出了問題能不能從日誌定位。

元件名字認識得再多,如果這些沒有做,服務還是不穩。先把一個小服務做完整,再逐步加元件,更容易理解每一步為什麼要這麼做。

相關記錄

Consul:服務註冊與發現、微服務框架、Kratos、go-zero。

關於這篇文章的日期

舊日期 2025-01-16 與文章發布記錄不符,現按舊站可確認的首次發布日 2026-01-20 整理。實際創作日期尚無法確認。 舊頁僅有佔位標題,正文於 2026-10-06 補充。

原始日期: 2025-01-16 21:15:06 +0800