1
0
mirror of https://github.com/go-kratos/kratos.git synced 2025-10-30 23:47:59 +02:00

refactor(all): replace atomic functions with atomic types (#3699)

Co-authored-by: 1911860538 <alxps1911@gmail.com>
This commit is contained in:
Name
2025-09-04 20:42:51 +08:00
committed by GitHub
parent 3c0775892e
commit 4a1ed45fa6
7 changed files with 44 additions and 44 deletions

View File

@@ -24,7 +24,7 @@ type Discovery struct {
httpClient *resty.Client httpClient *resty.Client
node atomic.Value node atomic.Value
nodeIdx uint64 nodeIdx atomic.Uint64
mutex sync.RWMutex mutex sync.RWMutex
apps map[string]*appInfo apps map[string]*appInfo
@@ -217,11 +217,11 @@ func (d *Discovery) pickNode() string {
if !ok || len(nodes) == 0 { if !ok || len(nodes) == 0 {
return d.config.Nodes[rand.Intn(len(d.config.Nodes))] return d.config.Nodes[rand.Intn(len(d.config.Nodes))]
} }
return nodes[atomic.LoadUint64(&d.nodeIdx)%uint64(len(nodes))] return nodes[d.nodeIdx.Load()%uint64(len(nodes))]
} }
func (d *Discovery) switchNode() { func (d *Discovery) switchNode() {
atomic.AddUint64(&d.nodeIdx, 1) d.nodeIdx.Add(1)
} }
// renew an instance with Discovery // renew an instance with Discovery

View File

@@ -21,7 +21,7 @@ type watcher struct {
conn *zk.Conn conn *zk.Conn
cancel context.CancelFunc cancel context.CancelFunc
first uint32 first atomic.Bool
// prefix for ZooKeeper paths or keys (used for filtering or identifying watched nodes) // prefix for ZooKeeper paths or keys (used for filtering or identifying watched nodes)
prefix string prefix string
// the name of the service being watched in ZooKeeper // the name of the service being watched in ZooKeeper
@@ -61,7 +61,7 @@ func (w *watcher) watch(ctx context.Context) {
func (w *watcher) Next() ([]*registry.ServiceInstance, error) { func (w *watcher) Next() ([]*registry.ServiceInstance, error) {
// TODO: multiple calls to Next may lead to inconsistent service instance information // TODO: multiple calls to Next may lead to inconsistent service instance information
if atomic.CompareAndSwapUint32(&w.first, 0, 1) { if w.first.CompareAndSwap(false, true) {
return w.getServices() return w.getServices()
} }
select { select {

View File

@@ -11,7 +11,7 @@ type mergeCtx struct {
parent1, parent2 context.Context parent1, parent2 context.Context
done chan struct{} done chan struct{}
doneMark uint32 doneMark atomic.Bool
doneOnce sync.Once doneOnce sync.Once
doneErr error doneErr error
@@ -41,7 +41,7 @@ func Merge(parent1, parent2 context.Context) (context.Context, context.CancelFun
func (mc *mergeCtx) finish(err error) error { func (mc *mergeCtx) finish(err error) error {
mc.doneOnce.Do(func() { mc.doneOnce.Do(func() {
mc.doneErr = err mc.doneErr = err
atomic.StoreUint32(&mc.doneMark, 1) mc.doneMark.Store(true)
close(mc.done) close(mc.done)
}) })
return mc.doneErr return mc.doneErr
@@ -73,7 +73,7 @@ func (mc *mergeCtx) Done() <-chan struct{} {
// Err implements context.Context. // Err implements context.Context.
func (mc *mergeCtx) Err() error { func (mc *mergeCtx) Err() error {
if atomic.LoadUint32(&mc.doneMark) != 0 { if mc.doneMark.Load() {
return mc.doneErr return mc.doneErr
} }
var err error var err error

View File

@@ -109,8 +109,8 @@ func TestFinish(t *testing.T) {
if !errors.Is(err, context.DeadlineExceeded) { if !errors.Is(err, context.DeadlineExceeded) {
t.Errorf("expect %v, got %v", context.DeadlineExceeded, err) t.Errorf("expect %v, got %v", context.DeadlineExceeded, err)
} }
if !reflect.DeepEqual(mc.doneMark, uint32(1)) { if done := mc.doneMark.Load(); done != true {
t.Errorf("expect %v, got %v", 1, mc.doneMark) t.Errorf("expect %v, got %v", true, done)
} }
if <-mc.done != struct{}{} { if <-mc.done != struct{}{} {
t.Errorf("expect %v, got %v", struct{}{}, <-mc.done) t.Errorf("expect %v, got %v", struct{}{}, <-mc.done)

View File

@@ -22,7 +22,7 @@ type Node struct {
selector.Node selector.Node
// last lastPick timestamp // last lastPick timestamp
lastPick int64 lastPick atomic.Int64
} }
// Builder is direct node builder // Builder is direct node builder
@@ -30,12 +30,12 @@ type Builder struct{}
// Build create node // Build create node
func (*Builder) Build(n selector.Node) selector.WeightedNode { func (*Builder) Build(n selector.Node) selector.WeightedNode {
return &Node{Node: n, lastPick: 0} return &Node{Node: n, lastPick: atomic.Int64{}}
} }
func (n *Node) Pick() selector.DoneFunc { func (n *Node) Pick() selector.DoneFunc {
now := time.Now().UnixNano() now := time.Now().UnixNano()
atomic.StoreInt64(&n.lastPick, now) n.lastPick.Store(now)
return func(context.Context, selector.DoneInfo) {} return func(context.Context, selector.DoneInfo) {}
} }
@@ -48,7 +48,7 @@ func (n *Node) Weight() float64 {
} }
func (n *Node) PickElapsed() time.Duration { func (n *Node) PickElapsed() time.Duration {
return time.Duration(time.Now().UnixNano() - atomic.LoadInt64(&n.lastPick)) return time.Duration(time.Now().UnixNano() - n.lastPick.Load())
} }
func (n *Node) Raw() selector.Node { func (n *Node) Raw() selector.Node {

View File

@@ -28,16 +28,16 @@ type Node struct {
selector.Node selector.Node
// client statistic data // client statistic data
lag int64 lag atomic.Int64
success uint64 success atomic.Uint64
inflight int64 inflight atomic.Int64
inflights [200]int64 inflights [200]atomic.Int64
// last collected timestamp // last collected timestamp
stamp int64 stamp atomic.Int64
// request number in a period time // request number in a period time
reqs int64 reqs atomic.Int64
// last lastPick timestamp // last lastPick timestamp
lastPick int64 lastPick atomic.Int64
errHandler func(err error) (isErr bool) errHandler func(err error) (isErr bool)
cachedWeight *atomic.Value cachedWeight *atomic.Value
@@ -57,27 +57,27 @@ type Builder struct {
func (b *Builder) Build(n selector.Node) selector.WeightedNode { func (b *Builder) Build(n selector.Node) selector.WeightedNode {
s := &Node{ s := &Node{
Node: n, Node: n,
lag: 0, inflights: [200]atomic.Int64{},
success: 1000,
inflight: 1,
errHandler: b.ErrHandler, errHandler: b.ErrHandler,
cachedWeight: &atomic.Value{}, cachedWeight: &atomic.Value{},
} }
s.success.Store(1000)
s.inflight.Store(1)
return s return s
} }
func (n *Node) health() uint64 { func (n *Node) health() uint64 {
return atomic.LoadUint64(&n.success) return n.success.Load()
} }
func (n *Node) load() (load uint64) { func (n *Node) load() (load uint64) {
now := time.Now().UnixNano() now := time.Now().UnixNano()
avgLag := atomic.LoadInt64(&n.lag) avgLag := n.lag.Load()
predict := n.predict(avgLag, now) predict := n.predict(avgLag, now)
if avgLag == 0 { if avgLag == 0 {
// penalty is the penalty value when there is no data when the node is just started. // penalty is the penalty value when there is no data when the node is just started.
load = penalty * uint64(atomic.LoadInt64(&n.inflight)) load = penalty * uint64(n.inflight.Load())
return return
} }
if predict > avgLag { if predict > avgLag {
@@ -86,7 +86,7 @@ func (n *Node) load() (load uint64) {
// add 5ms to eliminate the latency gap between different zones // add 5ms to eliminate the latency gap between different zones
avgLag += int64(time.Millisecond * 5) avgLag += int64(time.Millisecond * 5)
avgLag = int64(math.Sqrt(float64(avgLag))) avgLag = int64(math.Sqrt(float64(avgLag)))
load = uint64(avgLag) * uint64(atomic.LoadInt64(&n.inflight)) load = uint64(avgLag) * uint64(n.inflight.Load())
return load return load
} }
@@ -97,7 +97,7 @@ func (n *Node) predict(avgLag int64, now int64) (predict int64) {
totalNum int totalNum int
) )
for i := range n.inflights { for i := range n.inflights {
start := atomic.LoadInt64(&n.inflights[i]) start := n.inflights[i].Load()
if start != 0 { if start != 0 {
totalNum++ totalNum++
lag := now - start lag := now - start
@@ -116,20 +116,20 @@ func (n *Node) predict(avgLag int64, now int64) (predict int64) {
// Pick pick a node. // Pick pick a node.
func (n *Node) Pick() selector.DoneFunc { func (n *Node) Pick() selector.DoneFunc {
start := time.Now().UnixNano() start := time.Now().UnixNano()
atomic.StoreInt64(&n.lastPick, start) n.lastPick.Store(start)
atomic.AddInt64(&n.inflight, 1) n.inflight.Add(1)
reqs := atomic.AddInt64(&n.reqs, 1) reqs := n.reqs.Add(1)
slot := reqs % 200 slot := reqs % 200
swapped := atomic.CompareAndSwapInt64(&n.inflights[slot], 0, start) swapped := n.inflights[slot].CompareAndSwap(0, start)
return func(_ context.Context, di selector.DoneInfo) { return func(_ context.Context, di selector.DoneInfo) {
if swapped { if swapped {
atomic.CompareAndSwapInt64(&n.inflights[slot], start, 0) n.inflights[slot].CompareAndSwap(start, 0)
} }
atomic.AddInt64(&n.inflight, -1) n.inflight.Add(-1)
now := time.Now().UnixNano() now := time.Now().UnixNano()
// get moving average ratio w // get moving average ratio w
stamp := atomic.SwapInt64(&n.stamp, now) stamp := n.stamp.Swap(now)
td := now - stamp td := now - stamp
if td < 0 { if td < 0 {
td = 0 td = 0
@@ -140,12 +140,12 @@ func (n *Node) Pick() selector.DoneFunc {
if lag < 0 { if lag < 0 {
lag = 0 lag = 0
} }
oldLag := atomic.LoadInt64(&n.lag) oldLag := n.lag.Load()
if oldLag == 0 { if oldLag == 0 {
w = 0.0 w = 0.0
} }
lag = int64(float64(oldLag)*w + float64(lag)*(1.0-w)) lag = int64(float64(oldLag)*w + float64(lag)*(1.0-w))
atomic.StoreInt64(&n.lag, lag) n.lag.Store(lag)
success := uint64(1000) // error value ,if error set 1 success := uint64(1000) // error value ,if error set 1
if di.Err != nil { if di.Err != nil {
@@ -158,9 +158,9 @@ func (n *Node) Pick() selector.DoneFunc {
success = 0 success = 0
} }
} }
oldSuc := atomic.LoadUint64(&n.success) oldSuc := n.success.Load()
success = uint64(float64(oldSuc)*w + float64(success)*(1.0-w)) success = uint64(float64(oldSuc)*w + float64(success)*(1.0-w))
atomic.StoreUint64(&n.success, success) n.success.Store(success)
} }
} }
@@ -183,7 +183,7 @@ func (n *Node) Weight() (weight float64) {
} }
func (n *Node) PickElapsed() time.Duration { func (n *Node) PickElapsed() time.Duration {
return time.Duration(time.Now().UnixNano() - atomic.LoadInt64(&n.lastPick)) return time.Duration(time.Now().UnixNano() - n.lastPick.Load())
} }
func (n *Node) Raw() selector.Node { func (n *Node) Raw() selector.Node {

View File

@@ -34,7 +34,7 @@ func New(opts ...Option) selector.Selector {
type Balancer struct { type Balancer struct {
mu sync.Mutex mu sync.Mutex
r *rand.Rand r *rand.Rand
picked int64 picked atomic.Bool
} }
// choose two distinct nodes. // choose two distinct nodes.
@@ -71,9 +71,9 @@ func (s *Balancer) Pick(_ context.Context, nodes []selector.WeightedNode) (selec
// If the failed node has never been selected once during forceGap, it is forced to be selected once // If the failed node has never been selected once during forceGap, it is forced to be selected once
// Take advantage of forced opportunities to trigger updates of success rate and delay // Take advantage of forced opportunities to trigger updates of success rate and delay
if upc.PickElapsed() > forcePick && atomic.CompareAndSwapInt64(&s.picked, 0, 1) { if upc.PickElapsed() > forcePick && s.picked.CompareAndSwap(false, true) {
defer s.picked.Store(false)
pc = upc pc = upc
atomic.StoreInt64(&s.picked, 0)
} }
done := pc.Pick() done := pc.Pick()
return pc, done, nil return pc, done, nil