From 45f1bc0417211e9d22f11d645af12d10ff232fa2 Mon Sep 17 00:00:00 2001 From: h-hg <1394564544@qq.com> Date: Mon, 28 Aug 2023 15:40:01 +0800 Subject: [PATCH] fix: improve the design of nonce --- sdk/utils/utils.go | 60 +++++++++++++++++------------------------ sdk/utils/utils_test.go | 7 ++--- 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/sdk/utils/utils.go b/sdk/utils/utils.go index f8a3ad3840..8bd838b22e 100644 --- a/sdk/utils/utils.go +++ b/sdk/utils/utils.go @@ -15,15 +15,18 @@ package utils import ( + "bytes" "crypto/md5" "crypto/rand" "encoding/base64" "encoding/hex" "hash" - rand2 "math/rand" + "math/rand" "net/url" "reflect" + "runtime" "strconv" + "sync/atomic" "time" ) @@ -31,18 +34,28 @@ type UUID [16]byte const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" -func GetUUID() (uuidHex string) { - uuid := NewUUID() - uuidHex = hex.EncodeToString(uuid[:]) - return +var processStartTime int64 = time.Now().UnixNano() / 1e6 +var seqId int64 = 0 + +func getGID() uint64 { + // https://blog.sgmansfield.com/2015/12/goroutine-ids/ + b := make([]byte, 64) + b = b[:runtime.Stack(b, false)] + b = bytes.TrimPrefix(b, []byte("goroutine ")) + b = b[:bytes.IndexByte(b, ' ')] + n, _ := strconv.ParseUint(string(b), 10, 64) + return n } -func RandStringBytes(n int) string { - b := make([]byte, n) - for i := range b { - b[i] = letterBytes[rand2.Intn(len(letterBytes))] - } - return string(b) +func GetUUID() (uuidHex string) { + routineId := getGID() + currentTime := time.Now().UnixNano() / 1e6 + seq := atomic.AddInt64(&seqId, 1) + randNum := rand.Int63() + msg := fmt.Sprintf("%d-%d-%d-%d-%d", processStartTime, routineId, currentTime, seq, randNum) + h := md5.New() + h.Write([]byte(msg)) + return hex.EncodeToString(h.Sum(nil)) } func GetMD5Base64(bytes []byte) (base64Value string) { @@ -99,31 +112,6 @@ func InitStructWithDefaultTag(bean interface{}) { } } -func NewUUID() UUID { - ns := UUID{} - safeRandom(ns[:]) - u := newFromHash(md5.New(), ns, RandStringBytes(16)) - u[6] = (u[6] & 0x0f) | (byte(2) << 4) - u[8] = (u[8]&(0xff>>2) | (0x02 << 6)) - - return u -} - -func newFromHash(h hash.Hash, ns UUID, name string) UUID { - u := UUID{} - h.Write(ns[:]) - h.Write([]byte(name)) - copy(u[:], h.Sum(nil)) - - return u -} - -func safeRandom(dest []byte) { - if _, err := rand.Read(dest); err != nil { - panic(err) - } -} - func (u UUID) String() string { buf := make([]byte, 36) diff --git a/sdk/utils/utils_test.go b/sdk/utils/utils_test.go index 3ae46a15bb..86bdc630fc 100644 --- a/sdk/utils/utils_test.go +++ b/sdk/utils/utils_test.go @@ -26,11 +26,8 @@ func TestInitStructWithDefaultTag(t *testing.T) { } func TestGetUUID(t *testing.T) { - uuid := NewUUID() - assert.Equal(t, 16, len(uuid)) - assert.Equal(t, 36, len(uuid.String())) - uuidString := GetUUID() - assert.Equal(t, 32, len(uuidString)) + assert.Equal(t, 32, len(GetUUID())) + assert.NotEqual(t, GetUUID(), GetUUID()) } func TestGetMD5Base64(t *testing.T) {