From 288d78f66ecd1b628e8d1df7a3da99fc5e6880ec Mon Sep 17 00:00:00 2001 From: zhangqian <zhangqian@123.com> Date: 星期五, 08 十二月 2023 14:13:37 +0800 Subject: [PATCH] debug --- pkg/snowflake/snowflake.go | 178 +++++++++++++++++++++++++++------------------------------- 1 files changed, 83 insertions(+), 95 deletions(-) diff --git a/pkg/snowflake/snowflake.go b/pkg/snowflake/snowflake.go index ad86994..049b307 100644 --- a/pkg/snowflake/snowflake.go +++ b/pkg/snowflake/snowflake.go @@ -1,118 +1,106 @@ package snowflake import ( - "errors" - "strconv" - "sync" - "time" + "apsClient/pkg/logx" + "fmt" + "github.com/bwmarrin/snowflake" + "hash/fnv" + "net" ) -const ( - CEpoch = 1474802888000 - CWorkerIdBits = 10 // Num of WorkerId Bits - CSenquenceBits = 12 // Num of Sequence Bits +var Node *snowflake.Node - CWorkerIdShift = 12 - CTimeStampShift = 22 - - CSequenceMask = 0xfff // equal as getSequenceMask() - CMaxWorker = 0x3ff // equal as getMaxWorkerId() -) - -type IdWorker struct { - workerId int64 - lastTimeStamp int64 - sequence int64 - maxWorkerId int64 - lock *sync.Mutex -} - -func NewIdWorker(workerId int64) (iw *IdWorker, err error) { - iw = new(IdWorker) - - iw.maxWorkerId = getMaxWorkerId() - - if workerId > iw.maxWorkerId || workerId < 0 { - return nil, errors.New("worker not fit") +func Init(nodeId int64) error { + // Create a new Node with a Node number of 0~1023 + var err error + Node, err = snowflake.NewNode(nodeId) + if err != nil { + logx.Errorf("snowflake NewNode error:%v", err) + return err } - iw.workerId = workerId - iw.lastTimeStamp = -1 - iw.sequence = 0 - iw.lock = new(sync.Mutex) - return iw, nil + return nil } -func getMaxWorkerId() int64 { - return -1 ^ -1<<CWorkerIdBits -} +func InitWithIP() { + // 浣跨敤 LookupIP 鑾峰彇涓绘満鐨� IP 鍦板潃鍒楄〃 + // 鑾峰彇鏈満鎵�鏈夌綉缁滄帴鍙� + interfaces, err := net.Interfaces() + if err != nil { + logx.Errorf("snowflake InitWithIP error:%v", err) + return + } -func getSequenceMask() int64 { - return -1 ^ -1<<CSenquenceBits -} - -// return in ms -func (iw *IdWorker) timeGen() int64 { - return time.Now().UnixNano() / 1000 / 1000 -} - -func (iw *IdWorker) timeReGen(last int64) int64 { - ts := time.Now().UnixNano() / 1000 / 1000 - for { - if ts <= last { - ts = iw.timeGen() - } else { - break + var ip string + // 閬嶅巻鎵�鏈夌綉缁滄帴鍙� + for _, iface := range interfaces { + // 鎺掗櫎涓�浜涚壒娈婄殑鎺ュ彛锛屼緥濡� loopback 鎺ュ彛 + if iface.Flags&net.FlagUp != 0 && iface.Flags&net.FlagLoopback == 0 { + // 鑾峰彇鎺ュ彛鐨勬墍鏈夊湴鍧� + addrs, err := iface.Addrs() + if err != nil { + logx.Errorf("snowflake InitWithIP error:%v", err) + continue + } + // 閬嶅巻鎺ュ彛鐨勬墍鏈夊湴鍧� + for _, addr := range addrs { + // 妫�鏌ュ湴鍧�绫诲瀷鏄惁鏄� IP 鍦板潃 + if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() { + // 鍒ゆ柇 IP 鍦板潃鐨勭増鏈槸 IPv4 杩樻槸 IPv6 + if ipNet.IP.To4() != nil { + fmt.Printf("IPv4 Address: %s\n", ipNet.IP.String()) + if ipNet.IP.String() != "127.0.0.1" { + ip = ipNet.IP.String() + goto getIpOK + } + } else { + fmt.Printf("IPv6 Address: %s\n", ipNet.IP.String()) + } + } + } } } - return ts +getIpOK: + if ip == "" { + logx.Errorf("snowflake InitWithIP can not find Ip") + return + } + ipNumber, err := ipToNumber(ip) + if err != nil { + logx.Errorf("snowflake can not generate, init error, ip to number error :%v", err) + panic(fmt.Sprintf("snowflake can not generate, init error, ip to number error :%v", err)) + } + err = Init(ipNumber) + if err != nil { + logx.Errorf("snowflake can not generate, init error :%v", err) + panic(fmt.Sprintf("snowflake can not generate, init error :%v", err)) + } } -func (iw *IdWorker) NextId() (ts int64, err error) { - iw.lock.Lock() - defer iw.lock.Unlock() - ts = iw.timeGen() - if ts == iw.lastTimeStamp { - iw.sequence = (iw.sequence + 1) & CSequenceMask - if iw.sequence == 0 { - ts = iw.timeReGen(ts) - } - } else { - iw.sequence = 0 - } - - if ts < iw.lastTimeStamp { - err = errors.New("Clock moved backwards, Refuse gen id") +func StringToNumber(input string) (int64, error) { + hash := fnv.New32a() + _, err := hash.Write([]byte(input)) + if err != nil { return 0, err } - iw.lastTimeStamp = ts - ts = (ts-CEpoch)<<CTimeStampShift | iw.workerId<<CWorkerIdShift | iw.sequence - return ts, nil + return int64(hash.Sum32() % 1024), nil // 鍙栦綑鏁扮‘淇濈粨鏋滃湪 1 鍒� 1023 涔嬮棿 } -func ParseId(id int64) (t time.Time, ts int64, workerId int64, seq int64) { - seq = id & CSequenceMask - workerId = (id >> CWorkerIdShift) & CMaxWorker - ts = (id >> CTimeStampShift) + CEpoch - t = time.Unix(ts/1000, (ts%1000)*1000000) - return -} - -var idGenerater, _ = NewIdWorker(0) - -func GenerateId() int64 { -start: - id, err := idGenerater.NextId() - if err != nil { - goto start +func ipToNumber(ip string) (int64, error) { + // 灏� IP 鍦板潃瀛楃涓茶В鏋愪负 net.IP 绫诲瀷 + parsedIP := net.ParseIP(ip) + if parsedIP == nil { + return 0, fmt.Errorf("invalid IP address:%v", ip) } - return id + + // 浣跨敤 FNV-1a 鏁e垪绠楁硶璁$畻鍝堝笇鍊� + hash := fnv.New32a() + hash.Write(parsedIP) + return int64(hash.Sum32() % 1024), nil // 鍙栦綑鏁扮‘淇濈粨鏋滃湪 1 鍒� 1023 涔嬮棿 } -func GenerateIdStr() string { -start: - id, err := idGenerater.NextId() - if err != nil { - goto start +func GenerateID() int64 { + if Node == nil { + InitWithIP() } - return strconv.FormatInt(id, 10) + return int64(Node.Generate()) } -- Gitblit v1.8.0