aegis

command module
v0.0.0-...-b913f3f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 30, 2026 License: Apache-2.0 Imports: 41 Imported by: 0

README

Aegis 分散式鎖服務 (Distributed Lock Service)

Aegis 是一個基於 Go 語言開發的輕量級分散式鎖服務 (Distributed Lock Service),提供簡單易用的 RESTful API 來進行鎖的獲取、釋放與展期。系統設計支援可插拔的儲存後端,目前已實作 Redis、DynamoDB、PostgreSQL 與 MySQL 四種儲存引擎。

🌟 主要功能

  • 標準 HTTP API:提供單一且標準的 RESTful API 溝通介面。
  • 多儲存後端支援
    • Redis:適用於高併發、低延遲的快取鎖場景。
    • DynamoDB:適用於需要高可用性與持久化儲存的雲原生環境。
    • PostgreSQL:適用於需要關聯式資料庫整合、交易能力與持久化鎖管理的場景。
    • MySQL:適用於既有 MySQL 生態系中,需要以資料庫實作分散式鎖的場景。
  • 鎖生命週期管理:支援獲取鎖 (Acquire)、釋放鎖 (Release) 以及鎖展期 (Extend/Renew)。

🚀 快速開始

使用 Docker Compose 啟動 Redis 與 Aegis 服務
docker-compose up -d redis aegis

docker-compose.yml 會自動掛載 config.docker.yaml,讓 Aegis 在容器內使用 redis:6379 連線。

啟動依賴服務
or 啟動單一依賴服務 Redis
docker-compose up -d redis
執行服務
使用 Go 執行服務
go run main.go

預設伺服器會依照設定連接至對應的 backend 並在本地特定的 port 啟動監聽。

若要切換後端,可在 config.yaml 中設定 backendredisdynamodbpostgresmysql;使用 SQL 後端時,再搭配設定 sql.dialectsql.dsn

使用 Docker Image 啟動服務
docker pull ghcr.io/walnut-almonds/aegis:latest
docker run -d -p 8080:8080 --name aegis ghcr.io/walnut-almonds/aegis:latest
分別啟動 Redis 與 Aegis 容器

當需要獨立啟動 Redis 與 Aegis 容器時,需要確保它們在同一 Docker 網路上。

先在本地建置最新 image(確保可使用 REDIS_ADDR):

docker build -t aegis-server:local .
方式 1:創建共同網路(推薦)
# 建立 Docker 網路
docker network create aegis-net

# 啟動 Redis
docker run -d --name redis --network aegis-net redis:7-alpine

# 啟動 Aegis(透過環境變數指定 Redis 位址)
docker run -d -p 8080:8080 -p 50051:50051 \
  --network aegis-net \
  -e REDIS_ADDR=redis:6379 \
  --name aegis aegis-server:local
方式 2:透過主機轉發連線
# 啟動 Redis(port 6379)
docker run -d -p 6379:6379 --name redis redis:7-alpine

# 啟動 Aegis(從容器連回主機上的 Redis)
docker run -d -p 8080:8080 -p 50051:50051 \
  -e REDIS_ADDR=host.docker.internal:6379 \
  --name aegis aegis-server:local

Linux 若無 host.docker.internal,可加上 --add-host host.docker.internal:host-gateway

方式 3:指定 Redis 容器 IP
# 啟動 Redis,記下容器 IP
docker run -d --name redis redis:7-alpine
REDIS_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis)

# 啟動 Aegis,直接連接到 Redis 容器 IP
docker run -d -p 8080:8080 -p 50051:50051 \
  -e REDIS_ADDR=${REDIS_IP}:6379 \
  --name aegis aegis-server:local

📚 API 文件

HTTP API 由 Huma 自動註冊並產生 OpenAPI 文件。

  • OpenAPI JSON: /openapi.json
  • OpenAPI YAML: /openapi.yaml
  • 互動文件 UI: /docs

若要匯出可版控的靜態 OpenAPI 檔案:

go run . --export-openapi --openapi-out openapi/openapi.yaml

所有的 API 請求皆採用 JSON 格式,核心的資料模型如下:

{
  "key": "resource:123",  // 鎖的唯一鍵值 (Resource ID)
  "token": "uuid-xxxx",   // 用戶端/擁有者的唯一識別碼
  "ttl_sec": 30           // 鎖定存活時間 (秒)
}
1. 獲取鎖 (Acquire)
  • Method: POST /api/v1/lock/acquire
  • 說明: 嘗試獲取指定 key 的鎖。若鎖已被其他 token 持有,將回傳 409 Conflict。
  • Success Response: 201 Created
2. 釋放鎖 (Release)
  • Method: POST /api/v1/lock/release
  • 說明: 使用獲取鎖時的 token 來釋放鎖。若 token 不符或鎖已過期,則無法刪除(避免誤刪別人的鎖)。
  • Success Response: 200 OK
3. 鎖展期 (Extend)
  • Method: POST /api/v1/lock/extend
  • 說明: 當現有操作尚未完成,但鎖即將過期時,可以帶上正確的 token 來延長 ttl_sec
  • Success Response: 200 OK
4. 等待鎖 (WaitLock / Long-polling)
  • Method: POST /api/v1/lock/wait
  • 說明: 嘗試取得鎖;若目前被持有,伺服器會在 wait_timeout_sec 內持續等待並重試(long-polling),直到取得鎖或逾時。
  • Success Response: 201 Created
  • Timeout Response: 408 Request Timeout

請求範例:

{
  "key": "resource:123",
  "token": "uuid-xxxx",
  "ttl_sec": 30,
  "wait_timeout_sec": 10,
  "poll_interval_ms": 100
}

🛠️ 開發與測試

本專案測試整合了 testcontainers-go 與 miniredis:

執行單元測試 (Unit Tests)
go test -v ./... ./sdk/go/...
執行 Benchmark 測試

Benchmark 測試涵蓋 Redis、PostgreSQL、MySQL 三個後端,分為循序吞吐量、高並發吞吐量、鎖競爭三種情境。完整的測試結果與分析請參閱 benchmark.md

跑全部 Benchmark
go test -bench=. -benchtime=3s -benchmem ./...
只跑指定後端
# 只跑 Redis
go test -bench=^BenchmarkRedis_ -benchtime=5s -benchmem ./...

# 只跑 PostgreSQL
go test -bench=^BenchmarkPostgres_ -benchtime=5s -benchmem ./...

# 只跑 MySQL
go test -bench=^BenchmarkMySQL_ -benchtime=5s -benchmem ./...
只跑特定情境
# 高並發吞吐量(各後端 goroutine=1/4/16/64)
go test -bench=Concurrent -benchtime=3s -benchmem ./...

# 鎖競爭率(多 goroutine 搶同一把鎖)
go test -bench=Contention -benchtime=3s -benchmem ./...
延遲百分位測試(p50 / p95 / p99)
go test -run=TestLatencyPercentile -v ./...

加上 -short 旗標可略過延遲測試:go test -short ./...

執行 Lint 檢查

確保已安裝 golangci-lint,再執行以下指令:

golangci-lint run ./...

若需同時對 SDK 模組進行 lint:

golangci-lint run ./...
cd sdk/go && golangci-lint run ./...

or

# (似乎在某些環境下不支援)
golangci-lint run ./... sdk/go/...

授權

本專案採用 Apache License 2.0 授權 - 詳見 LICENSE 檔案

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
pb module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL