server.md - maoxiaoyue/hypgo GitHub Wiki
Server Package (pkg/server)
server 套件是 HypGo 框架的網路層核心,負責傾聽連接埠、處理連線,以及協調底層通訊協定與上層的 router。它支援多種協議的自動切換與同時運行,並提供優雅重啟 (Graceful Restart) 以達到零停機部署。
主要特色
- 多通訊協定支援: 支援單純的 HTTP/1.1,也支援基於
h2c的透明 HTTP/2,更支援基於 UDP QUIC 協定的 HTTP/3 服務。 - Auto Protocol 模式: 只要開啟 TLS 並選擇 Auto 模式(或是設定
server.protocol: auto),便會同時啟動 HTTP/1.1、HTTP/2 與 HTTP/3 的服務,自動與瀏覽器協商最佳協定。 - Graceful Shutdown: 收到
SIGINT或SIGTERM訊號時,伺服器將拒絕新連線但確保已建立的請求處理完畢後才退出,並支援超時強行關閉。HTTP/1+2 與 HTTP/3 伺服器並行 shutdown。 - Graceful Restart (僅支援 Unix): 透過發送自訂訊號(例如預設的
SIGUSR2),能夠觸發 Fork 新程序接替傾聽相同的 Port,然後舊程序在處理完手頭的請求後退出,達成零停機。 - 自動 PID 管理: 啟動時自動寫入 PID 檔案,方便使用腳本或監控系統追蹤程序。
- AutoSync 自動同步:
Start()時自動產出.hyp/context.yamlmanifest,AI 永遠可取得最新專案結構。
基礎使用
利用 config 初始化並啟動伺服器:
package main
import (
"log"
"github.com/maoxiaoyue/hypgo/pkg/config"
"github.com/maoxiaoyue/hypgo/pkg/logger"
"github.com/maoxiaoyue/hypgo/pkg/server"
)
func main() {
// 1. 讀取配置
cfg, _ := config.LoadConfig("config.yaml")
// 2. 初始化 Logger
logInstance, _ := logger.New("info", "stdout", nil, true)
// 3. 建立伺服器實例
srv := server.New(cfg, logInstance)
// 4. 定義路由 (取得內建的 Router)
r := srv.Router()
r.GET("/api/ping", func(c *context.Context) {
c.String(200, "pong")
})
// 5. 啟動伺服器 (會阻塞直到收到關閉訊號)
if err := srv.Start(); err != nil {
log.Fatalf("伺服器發生錯誤: %v", err)
}
}
配置範例
在 config.yaml 控制 Protocol 與 TLS 行為:
server:
addr: ":443"
protocol: "auto" # 支援 http1, http2, http3, auto
graceful_restart: true # 監聽重啟訊號 (Unix only)
tls:
enabled: true # 若是 http3 或 auto 這裡必須是 true
cert_file: "/path/to/cert.pem"
key_file: "/path/to/key.pem"
自訂路由與中間件結合
server.New() 已封裝並實例化 router.Router。透過 srv.Router() 呼叫所有 Router 功能:
r := srv.Router()
// 掛載全域中間件
r.Use(middleware.Logger(middleware.LoggerConfig{}))
// 掛載靜態檔案
r.Static("/public", "./assets")
// 自訂 404 處理器(委派給 Router)
srv.NotFound(func(c *context.Context) {
c.String(404, "Page Not Found!")
})
// 自訂 405 處理器(委派給 Router)
srv.MethodNotAllowed(func(c *context.Context) {
c.String(405, "Method Not Allowed!")
})
三協議架構設計
HTTP/1.1 (startHTTP1)
- 標準 TCP 監聽
- 支援 TLS(使用統一 cipher suites)
- 可選 Keep-Alive
HTTP/2 (startHTTP2WithFallback)
- 透過
h2c.NewHandler支援明文 HTTP/2(開發環境) - TLS 模式自動 ALPN 協商
h2/http/1.1 - HTTP/2 設定驗證:
MaxReadFrameSize:限制 16KB~16MB(HTTP/2 spec 規範)MaxConcurrentStreams:預設 250IdleTimeout:可配置
HTTP/3 (startHTTP3)
- 基於 QUIC(UDP),要求 TLS 1.3
- 使用
quic-go/http3套件 - 自動設定
Alt-Svcheader 引導瀏覽器升級
Auto Protocol
同時啟動 HTTP/3(UDP goroutine)+ HTTP/2+1.1(TCP 主線程):
Client → TCP → HTTP/1.1 or HTTP/2 (via ALPN)
Client → UDP → HTTP/3 (via Alt-Svc header upgrade)
TLS 安全設計
統一 Cipher Suites
三種協議共用 strongCipherSuites,確保一致的安全等級:
var strongCipherSuites = []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
}
- HTTP/1.1 + HTTP/2:
MinVersion = TLS 1.2 - HTTP/3:
MinVersion = TLS 1.3(QUIC 強制要求)
0-RTT Session Cache(防 Replay Attack)
TLS 1.3 的 0-RTT 恢復功能使用帶保護的 SessionCache:
// SessionCache 特性:
// - maxSize = 10,000 條目(防止記憶體耗盡 DoS)
// - TTL = 24 小時(過期自動淘汰)
// - LRU 淘汰:超過上限時移除最舊條目
// - GetAndDelete 原子操作:防止 race window replay attack
| 操作 | 安全保證 |
|---|---|
Put() |
檢查大小上限 → 淘汰過期 → 淘汰最舊 → 儲存 |
GetAndDelete() |
原子取得並刪除,同一 session 只能使用一次 |
證書載入
loadCertificate() 回傳 (tls.Certificate, error) 而非 panic,確保生產環境不會因證書問題導致整個伺服器崩潰。
Graceful Shutdown
並行 Shutdown
HTTP/1+2 和 HTTP/3 伺服器同時關閉,共用 context timeout:
// Shutdown 內部行為:
// 1. shuttingDown.Store(true) ← atomic,無競態
// 2. listener.Close() ← 停止接受新連線
// 3. 並行:httpServer.Shutdown(ctx) + h3Server.Close()
// 4. close(shutdownChan) ← 通知 graceful restart goroutine 退出
Graceful Restart(Unix)
1. 收到 SIGUSR2
2. Fork 新進程(傳遞 listener FD)
3. Poll 等待新進程就緒(每 200ms × 15 次 = 3 秒)
4. 舊進程 Shutdown(30 秒 timeout)
5. 移除 PID 檔案 → Exit
安全修復:
signal.Stop確保信號訂閱被清理file.Close()防止 FD 洩漏getInheritedListener驗證 FD 3 確實是 TCP socket
shuttingDown 競態防護
使用 atomic.Bool 取代 bool,確保 Shutdown() 寫入與 Health() 讀取之間無 data race:
// 寫入(Shutdown 時)
s.shuttingDown.Store(true)
// 讀取(Health 檢查)
if s.shuttingDown.Load() { ... }
Project Manifest(AI 協作)
Server 提供 Manifest() 方法,自動掃描已註冊的路由、設定與 schema metadata,產出機器可讀的專案描述:
m := srv.Manifest()
manifest.WriteYAML(os.Stdout, m)
manifest.SaveToFile(".hyp/manifest.yaml", m, "yaml")
輸出範例:
version: "1.0"
framework: HypGo
server:
addr: ":8080"
protocol: http2
tls: true
routes:
- method: POST
path: /api/users
handler_names: [controllers.CreateUser]
summary: "建立使用者"
tags: [users]
input_type: CreateUserRequest
output_type: UserResponse
database:
driver: postgres
has_replicas: true
也可透過 CLI 使用:
hyp context # YAML 到 stdout
hyp context -f json # JSON 格式
hyp context -o manifest.yaml # 儲存到檔案
AutoSync 自動同步
Server.Start() 在啟動時自動呼叫 autosync.SyncSafe(),產出 .hyp/context.yaml:
- 原子寫入:使用 temp file +
os.Rename()防止寫入中途損壞 - 安全:不包含密碼、token、DSN 等敏感資訊
- 自動:每次 Server 啟動時更新,無需額外命令