From 20bbbcc1d14536ddaa498ac84a6008828df8dc1c Mon Sep 17 00:00:00 2001
From: zhangqian <zhangqian@123.com>
Date: 星期三, 13 十二月 2023 20:23:11 +0800
Subject: [PATCH] 往plc写目标数时,优先往写入地址写,没有写入地址再往读取地址写
---
pkg/snowflake/snowflake.go | 186 +++++++++++++++++++++++++++++++++++++---------
1 files changed, 148 insertions(+), 38 deletions(-)
diff --git a/pkg/snowflake/snowflake.go b/pkg/snowflake/snowflake.go
index 52420db..f0f6442 100644
--- a/pkg/snowflake/snowflake.go
+++ b/pkg/snowflake/snowflake.go
@@ -2,61 +2,70 @@
import (
"apsClient/pkg/logx"
+ "errors"
"fmt"
- "github.com/bwmarrin/snowflake"
"hash/fnv"
"net"
+ "strconv"
+ "sync"
+ "time"
)
-var Node *snowflake.Node
+var idGenerater *IdWorker
-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
- }
- return nil
-}
-
-func InitWithIP() {
+func init() {
// 浣跨敤 LookupIP 鑾峰彇涓绘満鐨� IP 鍦板潃鍒楄〃
- addrs, err := net.LookupIP("localhost")
+ // 鑾峰彇鏈満鎵�鏈夌綉缁滄帴鍙�
+ interfaces, err := net.Interfaces()
if err != nil {
- logx.Errorf("snowflake can not generate, init error, get ip error:%v", err)
- panic(fmt.Sprintf("snowflake can not generate, init error, get ip error:%v", err))
+ logx.Errorf("snowflake InitWithIP error:%v", err)
+ return
}
+
var ip string
- // 閬嶅巻 IP 鍦板潃鍒楄〃
- for _, addr := range addrs {
- // 鍒ゆ柇 IP 鍦板潃鐨勭増鏈槸 IPv4 杩樻槸 IPv6
- if ipNet := addr.To4(); ipNet != nil {
- ip = ipNet.String()
- logx.Errorf("IPv4 Address: %s\n", ipNet.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())
+ }
+ }
+ }
}
}
-
+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)
+ idGenerater, err = NewIdWorker(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 StringToNumber(input string) (int64, error) {
- hash := fnv.New32a()
- _, err := hash.Write([]byte(input))
- if err != nil {
- return 0, err
- }
- return int64(hash.Sum32() % 1024), nil // 鍙栦綑鏁扮‘淇濈粨鏋滃湪 1 鍒� 1023 涔嬮棿
}
func ipToNumber(ip string) (int64, error) {
@@ -72,9 +81,110 @@
return int64(hash.Sum32() % 1024), nil // 鍙栦綑鏁扮‘淇濈粨鏋滃湪 1 鍒� 1023 涔嬮棿
}
-func GenerateID() int64 {
- if Node == nil {
- InitWithIP()
+const (
+ CEpoch = 1474802888000
+ CWorkerIdBits = 10 // Num of WorkerId Bits
+ CSenquenceBits = 12 // Num of Sequence Bits
+
+ 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")
}
- return int64(Node.Generate())
+ iw.workerId = workerId
+ iw.lastTimeStamp = -1
+ iw.sequence = 0
+ iw.lock = new(sync.Mutex)
+ return iw, nil
+}
+
+func getMaxWorkerId() int64 {
+ return -1 ^ -1<<CWorkerIdBits
+}
+
+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
+ }
+ }
+ return ts
+}
+
+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")
+ return 0, err
+ }
+ iw.lastTimeStamp = ts
+ ts = (ts-CEpoch)<<CTimeStampShift | iw.workerId<<CWorkerIdShift | iw.sequence
+ return ts, nil
+}
+
+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
+}
+
+func GenerateID() int64 {
+start:
+ id, err := idGenerater.NextId()
+ if err != nil {
+ goto start
+ }
+ return id
+}
+
+func GenerateIdStr() string {
+start:
+ id, err := idGenerater.NextId()
+ if err != nil {
+ goto start
+ }
+ return strconv.FormatInt(id, 10)
}
--
Gitblit v1.8.0