单二进制三角色 + Dock 适配器 + Swarm stack 达到可部署态;mgr1 实测订阅经 central-proxy bootstrap,探活 alive=41/52。 Co-authored-by: Cursor <cursoragent@cursor.com>
63 lines
1.4 KiB
Go
63 lines
1.4 KiB
Go
// ids.go:请求 ID 生成(ulid 形态语义:时间有序 + 随机;无外部依赖自实现)。
|
||
package gateway
|
||
|
||
import (
|
||
"crypto/rand"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
// idChars Crockford base32(ulid 兼容字符集,26 字符编码空间)。
|
||
const idChars = "0123456789abcdefghjkmnpqrstvwxyz"
|
||
|
||
// idMu 单调状态(同毫秒内保证有序)。
|
||
var (
|
||
idMu sync.Mutex
|
||
idLast int64
|
||
idSeq uint8
|
||
)
|
||
|
||
// newRequestID 生成 26 字符 ulid 风格请求 ID(48bit 毫秒时间 + 80bit 随机)。
|
||
func newRequestID() string {
|
||
ms := time.Now().UnixMilli()
|
||
idMu.Lock()
|
||
if ms == idLast {
|
||
idSeq++
|
||
} else {
|
||
idLast = ms
|
||
idSeq = 0
|
||
}
|
||
idMu.Unlock()
|
||
|
||
var out [26]byte
|
||
// 时间部分:前 10 字符(48bit 毫秒,高位在前)
|
||
t := uint64(ms) & ((1 << 48) - 1)
|
||
for i := 9; i >= 0; i-- {
|
||
out[i] = idChars[t&0x1f]
|
||
t >>= 5
|
||
}
|
||
// 随机部分:后 16 字符(80bit → 16×5bit)
|
||
var rnd [10]byte
|
||
if _, err := rand.Read(rnd[:]); err != nil {
|
||
// 环境级致命错误:退化为时间+计数填充,不 panic 影响服务面
|
||
for i := range rnd {
|
||
rnd[i] = byte(idSeq) ^ byte(i)
|
||
}
|
||
}
|
||
var bits uint64
|
||
var nbits uint
|
||
pos := 10
|
||
for _, b := range rnd {
|
||
bits = bits<<8 | uint64(b)
|
||
nbits += 8
|
||
for nbits >= 5 && pos < 26 {
|
||
nbits -= 5
|
||
out[pos] = idChars[(bits>>nbits)&0x1f]
|
||
pos++
|
||
}
|
||
}
|
||
if pos < 26 {
|
||
out[25] = idChars[(bits<<(5-nbits))&0x1f]
|
||
}
|
||
return string(out[:])
|
||
}
|