onesvm-browser-server/server/internal/gateway/ids.go
chii eb972dfa93 feat: 落地 browser-server 控制面并打通 mgr1 海外订阅
单二进制三角色 + Dock 适配器 + Swarm stack 达到可部署态;mgr1 实测订阅经 central-proxy bootstrap,探活 alive=41/52。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 15:05:12 +08:00

63 lines
1.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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[:])
}